トップページunix
988コメント297KB

シェルスクリプト総合 その24©5ch.net

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。 転載ダメ©2ch.net2014/11/11(火) 00:54:03.43
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 FreeBSDユーザは/bin/shの正体がashなので注意。
 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
  http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
  http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
 (理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その23
http://peace.2ch.net/test/read.cgi/unix/1404204950/
0676名無しさん@お腹いっぱい。2015/05/26(火) 20:32:22.47
>>671
ごめん。三項演算子に間違いがあった。
(r + 2) % 2 == 0 ? 3 : 4 )) in じゃなくて
(r + 2) % 4 == 0 ? 3 : 4 )) in だった。
以下楽しくなって、もう一つ書いといた。zshでしか動かないけれど。

a=(+ - \* /)
b ()
{
(( $# == 1 )) || b $@[1,-2]
total=$(( total $a[$(( ($# + 3) % 4 == 0 ? 1 : ($# + 2) % 4 == 0 ? 2 : ($# + 1) % 4 == 0 ? 3 : 4 ))] $@[-1] ))
echo $total
}
b $@


じゃあ勉強頑張って。
06776592015/05/26(火) 21:00:09.14
なぜか2で割ってるのはif文でつくり直してるときに気付きました!!
sh、zsh、bashの違いが何やら…
0678名無しさん@お腹いっぱい。2015/05/26(火) 22:22:51.71
>>677
そんなあなたにbusybox
0679名無しさん@お腹いっぱい。2015/05/27(水) 08:32:10.49
bashもzshも、shの機能を包括した上で拡張していて、shの構文なら共通して動くと捉えてれば良い
と思う。だからbashとzshは配列の扱いなど雑多な違いがある。以下昨日のbash版。
たぶんもっと簡素に書けるのだろうけど私も全然詳しくない。

a=(+ - \* /)
b ()
{
declare -a c=( $@ )
(( $# == 1 )) || b $( echo ${c[@]} |cut -d ' ' -f -$(( $# - 1 )) )
total=$(( total ${a[$(( ($# + 3) % 4 == 0 ? 0 : ($# + 2) % 4 == 0 ? 1 : ($# + 1) % 4 == 0 ? 2 : 3 ))]} ${c[$# - 1]} ))
echo $total
}
b $@


以下みたいな書き方も簡易な条件文。何が起こるのかは(( 1 ))した後にecho $?とかして
値を確認できる。c言語は0が偽だけどshellだと0が真なので注意。cでreturnで0返すでしょ。
さらに(( 0 ))などは、echo $?した時に0として返っていない事に注目。
(( 1 )) && echo true
(( 0 )) || echo true
自ら自らを呼ぶ、再帰関数は調べればすぐ出てくる。
declareは、再帰関数ゆえ、変数名が同じになってしまうから、関数を呼んだ側の変数の値を、
呼ばれた側が変える事が無いようにしている。ローカル変数とか、スコープとか調べると出てくる。
0680名無しさん@お腹いっぱい。2015/05/27(水) 10:46:37.27
シェルスクリプトに関するご質問です。

コマンドライン引数で指定されたキーワードに一致する部分を持つ、カレントディレクトリ配下のファイルをそのディレクトリ階層をそのままにコピーしたいのですが、何かよい方法はありますでしょうか。
何かよい方法はありますでしょうか。
実行環境はCentOSをTera Term とSSH接続している状態です。

実行例として
[user@portal ~]$ ./sample.sh A copyTo 
第1引数はキーワード、第2引数はコピー先のディレクトリ


これでコピーができたことをTera Term上で確認できることが望ましいです。
0681名無しさん@お腹いっぱい。2015/05/27(水) 11:05:38.31
ワイルドカード
0682名無しさん@お腹いっぱい。2015/05/27(水) 13:08:06.76
>>680
#!/bin/sh
find . -name "*$1*" | cpio -oc | (cd "$2" && cpio -ivdc)
0683名無しさん@お腹いっぱい。2015/05/27(水) 13:41:16.73
ワイルドカード使って自分で書いてみたらこんなのに…
#!/bin/sh
cp -Rv ["$1"] "$2"

>>682はビット演算子使っててよくわからないですが、目的の動作は確認致しました!
ありがとうございます!
0684名無しさん@お腹いっぱい。2015/05/27(水) 16:04:06.52
わざとトンチンカンなこと言ってんのかな
0685名無しさん@お腹いっぱい。2015/05/28(木) 10:32:09.00
>>663のやつ整数しか計算できないし、第1引数を0に足してるで
第1 + 第2 - 第3 * 第4 / 第5 + 第6 - …
って処理が正しい
0686名無しさん@お腹いっぱい。2015/05/28(木) 12:07:05.77
# こうすると動くよ。後は引数を実数にしてね。
total=$1; shift
a=(+ - \* /)
b ()
{
(( $# == 1 )) || b $@[1,-2]
total=$(( total $a[$(( ($# + 3) % 4 == 0 ? 1 : ($# + 2) % 4 == 0 ? 2 : ($# + 1) % 4 == 0 ? 3 : 4 ))] $@[-1] ))
echo $total
}
b $@
0687名無しさん@お腹いっぱい。2015/05/28(木) 12:23:47.19
そっか、%つかってるんだった。
まぁ本人じゃないだろうし引かせてもらおう。
0688名無しさん@お腹いっぱい。2015/05/28(木) 12:25:16.28
おそらく663のcodeに
total=$1; shift
だけでいいんじゃないかな。急ぎなので、確認して無いけど。
0689名無しさん@お腹いっぱい。2015/05/28(木) 12:32:06.05
いや%と関係ないか。$#にたいしてだったね。
0690名無しさん@お腹いっぱい。2015/05/28(木) 12:32:46.85
>>659
自分も、参考までに考えておいた
初期値は 0、引数の数は不定で、加算、減算、乗算、除算を繰り返すと解釈した

#! /bin/sh -x
while
total=$(
echo "( ${total:-0} ${1:++ $1} ${2:+- $2} ) ${3:+* $3} ${4:+/ $4}" | bc
)
[ 4 -lt $# ] && shift 4
do :
done

echo "ANSWER: ${total}"
exit


#! /bin/sh -x
while [ 0 -lt $# ]
do
total=$(
echo "( ${total:-0} + ${1:- 0} - ${2:- 0} ) * ${3:- 1} / ${4:- 1}" | bc
)
shift $(( $# > 4 ? 4 : $# ))
done

echo "ANSWER: ${total:-0}"
exit
0691名無しさん@お腹いっぱい。2015/05/28(木) 12:35:03.52
ああ、せっかく全角スペースで字下げしたのに、間違えてただのスペース打ち込んだか
0692名無しさん@お腹いっぱい。2015/05/28(木) 18:17:15.57
# 他の人のレスは後で確認する。なんだか覚醒してきた。dashで動くように作った。
# 以下をtest.shで保存。
#!/bin/sh
a='/+-*'
test $# -eq 1 && { echo $1; exit; } || total=$( ./test.sh $( echo $@ |cut -d ' ' -f -$(( $# - 1 )) ) )
echo $(( $total $( echo $a |cut -b $(( ( $# + 3 ) % 4 + 1 )) ) $( eval echo \$$#) ))
0693名無しさん@お腹いっぱい。2015/05/28(木) 21:33:17.29
大きな数の余りの計算とかできる?
0694名無しさん@お腹いっぱい。2015/05/28(木) 21:54:55.27
# 今その要求にshellだけで答えるように考えてる。
# 割り算部分はできたよ。もう疲れたからやめようかな。
# scaleの値を調整すれば何処まで計算するか指定できる。
# -の値を指定するとずっと計算し続けるので注意。
# dashで動くように書いてる。

#!bin/sh
scale=8
total=$1; shift

m ()
{
test $(( $3 )) -eq 0 -o $(( $1 )) -eq 0 && return
b=$1
a=$(( ${b}0 / $2 ))
echo -n $a
m $(( ${b}0 % $2 )) $2 $(( $3 - 1 )) # 余り、割る数、scale.
}
echo -n $(( total / $1 )).
m $(( total % $1 )) $1 $scale
0695名無しさん@お腹いっぱい。2015/05/28(木) 22:03:27.91
使い方書いてなかった。
./保存したfile 355 113
と引数二つです。
0696名無しさん@お腹いっぱい。2015/05/29(金) 02:54:31.46
よし諦めた。

>>690 本人じゃなくてわめいてる方ですけど、勉強になります。
一つ目書き方は知らないので勉強しておく事して二つ目ので見ると、
そっか、と思わされました。確かにその通りだと、コードも短いし理解もしやすいし。

>>659は彼のを参考にしたほうが良かと。私のは今考えて見ると三項演算子も無駄だったし、
ただ>>692は毒毒しい事をしているので、結構勉強になると思う。
0697名無しさん@お腹いっぱい。2015/05/29(金) 13:11:54.28
#!/bin/sh
# ごめん>>694 それ再帰してるから途中で計算できてなかった。
# 悪い所も無駄に関数な所も直して無いけど。以下でいける。
scale=-1
total=$1; shift

m ()
{
b=$1 # $1: 余り、$2: 割る数、$3: scale.
until test $scale = 0 -o b = 0
do
a=$(( ${b}0 / $2 ))
echo -n $a
b=$(( ${b}0 % $2 ))
scale=$(( scale - 1 ))
done
}
echo -n $(( total / $1 )).
m $(( total % $1 )) $1 $scale
0698名無しさん@お腹いっぱい。2015/05/29(金) 13:15:06.25
やば>>697まさかの$3 scale意味ない説。
0699名無しさん@お腹いっぱい。2015/05/29(金) 14:07:59.50
いやコメント内で使ってたか。
0700名無しさん@お腹いっぱい。2015/05/29(金) 17:25:17.77
なるほどdo whileみたいに使えるだね。
while false
true
do
echo test
break
done
前にfor分は以下で動くのになんでwhileは駄目なんだろうと思った、謎がとけました。
for r in *
{
echo $r
}
0701名無しさん@お腹いっぱい。2015/05/29(金) 17:41:57.11
ふむ、whileから最後の戻り値の間、do doneの間を回るわけだからdo whileとはまた違う。

離れ隠しとも名付けようかこの新手
0702名無しさん@お腹いっぱい。2015/05/29(金) 19:43:00.94
>> 696
> >>690 本人じゃなくてわめいてる方ですけど、勉強になります。
意外な効果で驚くなあ。でも、役に立って良かった

> 一つ目書き方は知らないので勉強しておく
って言葉で改めて見直すと

> 序盤のページで行き詰ってしまいました。
序盤で行き詰まっているんだよね。そんな人に対して適当な回答じゃあ無かったかもしれないなあ
( parameter substitution の機能とか使うべきではなかったか )と思い、妙なヒント入りでもう一度書いておきました



蛇足だけど、V7 Bourne Shell だと、:- でなく - なんだよね
http://www.in-ulm.de/~mascheck/bourne/v7/
> ${parameter-word}
> If parameter is set then substitute its value; otherwise substitute word.

それでなのか、POSIX でも定義されていて
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

bash や、dash でも echo ${HOGE-$HOME} が機能する



>>701
man dash, man bash, man ksh, man zshmisc と確認してみたけど
while list; do list; done 相当の事が書いてある
結構誰でも知っているて、新手では無いよ
0703名無しさん@お腹いっぱい。2015/05/29(金) 19:44:12.32
#! /bin/sh -x
total=0
while
 case $# in
 0)
  break
 ;;
 1)
  total=$( echo "${total} + $1" | bc )
  break
 ;;
 2)
  total=$( echo "( ${total} + $1 - $2 )" | bc )
  break
 ;;
 3)
  total=$( echo "( ${total} + $1 - $2 ) * $3" | bc )
  break
 ;;
0704名無しさん@お腹いっぱい。2015/05/29(金) 19:44:26.35
 4)
  total=$( echo "( ${total} + $1 - $2 ) * $3 / $4" | bc )
  break
 ;;
 [5-9]|[0-9]*[0-9])
  total=$( echo "( ${total} + $1 - $2 ) * $3 / $4" | bc )
  shift 4
  true
 ;;
 *)
  echo 'It never comes here and we know it.' >&2
  exit 1
 ;;
 esac
do : 'Do nothing with list-2 of "while list-1; do list-2; done"'
done

echo "ANSWER: ${total}"
exit
0705名無しさん@お腹いっぱい。2015/05/30(土) 04:04:02.38
# おかげさまで、また少し成長できました。


#!/bin/zsh
eval echo -n \${$#..1} \'$( yes '+-*/'|tr -d '\n' |dd bs=$(( $# - 1)) \
count=1 cbs=1 conv=unblock 2>/dev/null | sed 's#^#r#')\' p |dc


#!/bin/sh
{ eval echo -n $( seq -f "$%g" $# |tac ); echo "$( yes '+-*/'|tr -d '\n' \
|dd bs=$(( $# - 1)) count=1 cbs=1 conv=unblock 2>/dev/null | sed 's#^#r#' )" p; } |dc
0706名無しさん@お腹いっぱい。2015/05/30(土) 07:57:05.78
なんか凄いもの練り上げたね。なんか、スクリプトを書く 705 の楽しさが伝わってくるわw

eval echo $( seq -f "$%g" $# | tac )
の部分は "$@" とか使えないものかと思い、しばらく考えたんだが...

echo "$@ " | tac -s " "
0707名無しさん@お腹いっぱい。2015/05/31(日) 07:18:32.49
# 書けて良かった。

#!/bin/sh
eval echo 0 $( printf '$%d + $%d - $%d @ $%d /' $( seq $# ) | \
sed 's#+ $0#+ 0#g; s#- $0#- 1#g; s#@ $0#@ 1#g; a p' ) |tr '@' '*' |dc
0708名無しさん@お腹いっぱい。2015/05/31(日) 08:54:03.31
>>705
後段も書き換えてみた
echo "$( yes '+-*/'|tr -d '\n' \
|dd bs=$(( $# - 1)) count=1 cbs=1 conv=unblock 2>/dev/null | sed 's#^#r#' )" p


#! /bin/sh
# 何をするスクリプトかぱっと見で全くわからないので、一応書いておくけど、
# これも >>659 の回答
{
 echo "$@ " | tac -s " "
 yes 'r+r-r*r/' | tr -d '\n' | head -c $(( ( $# - 1 ) * 2 ))
 echo "p"
} | dc


>>707
アイデアが尽きないね。@は、エスケープ用かな?外しておいた

#! /bin/sh
eval echo 0 $(
 printf '$%d + $%d - $%d \\* $%d / ' $( seq $# ) |
 sed 's#+ $0#+ 0#g; s#- $0#- 1#g; s#* $0#* 1#g; a p'
) | dc
0709名無しさん@お腹いっぱい。2015/05/31(日) 11:51:51.69
大きな数の計算できるならRSA暗号化もできるんじゃないか?
0710名無しさん@お腹いっぱい。2015/05/31(日) 12:23:30.92
整形ついでに sed を整理してみた
eval とかなるべく使いたくないけど、printf で展開するアイデアが面白いな

#! /bin/sh
{
 eval echo 0 $(
  printf '$%d + $%d - $%d \\* $%d / ' $( seq $# ) |
   sed -e 's/$0 [+/*\-]* //g'
 )p
} | dc
0711名無しさん@お腹いっぱい。2015/05/31(日) 18:16:33.13
ちょっと危なっかしいけど、これで eval も外せたかな?

#! /bin/sh
{
 echo 0 $(
  n=$(( $# % 4 ))
  printf '%d + %d - %d \\* %d / ' "$@" |
   sed -e 's/\([0-9]\{1,\} [+/*\-]* \)\{'"$(( n == 0 ? 0 : 4 - n ))"'\}$//'
 )p
} | dc
0712名無しさん@お腹いっぱい。2015/06/01(月) 06:34:30.80
エスケープを外す前の方で書き込んでいた

訂正
#! /bin/sh
{
 echo "0 $(
  n=$(( $# % 4 ))
  printf '%d + %d - %d * %d / ' "$@" |
   sed -e 's/\([0-9]\{1,\} [+/*\-]* \)\{'"$(( n == 0 ? 0 : 4 - n ))"'\}$//'
 )p"
} | dc
0713名無しさん@お腹いっぱい。2015/06/02(火) 19:51:41.64
連投スマソ。printf 見直した

#! /bin/sh
echo "0 $( printf '%s + %s - %s * %s / ' "$@" "END" | sed -e 's/END.*$//' )p" | dc
0714名無しさん@お腹いっぱい。2015/06/02(火) 20:48:50.22
もうずいぶん前から計算違ってる
0715名無しさん@お腹いっぱい。2015/06/04(木) 06:35:03.60
解釈の違いだろ。echo も省いた

printf '%s + %s - %s * %s / ' "$@" "END" | sed -e 's/^/0 /; s/END.*$/p/' | dc
0716名無しさん@お腹いっぱい。2015/06/06(土) 17:40:55.66
先生のcodeを勉強する前に作っておきました。
ここのpageを見て理解しながら作りました。
http://www.maitou.gr.jp/rsa/
素数判定のアルゴリズムは以下のC言語のものを、冪乗の計算を一度に変えたものです。
http://ja.wikipedia.org/wiki/%E7%B4%A0%E6%95%B0%E5%88%A4%E5%AE%9A
今は一度コメントを全部消した状態で貼っておきます。
dcで書いてるので呪文っぽいので理解しようとしないほうが吉です。
そのうちbase64でコメントつけて貼るかもしれません。
factorにすぐやられますから、実用性は無いです。
dashで動くつもりでしたがzshでなければ動きません。
printf %d 010
とした時の挙動の違いに今気付きました。
0717名無しさん@お腹いっぱい。2015/06/06(土) 17:42:57.23
# $1から$2の範囲の素数を出力します。$2が省略された場合は$1一つの数に対して判定します。
# 例: prime 10000 20000
prime ()
{
dc -e "$( seq $1 ${2:-$1} )"'
z sc 0 sr [S2 lr 1 + sr lr lc >!] s! l! x
[[sg 3 Q] sk [p sg 3 Q] s.] sA
[d 2 >k d 2 =. d 2 % 0 =k] sB
[[sg 2 Q] sk [p sg 2 Q] s. d v s^ 3 s/] sC
[l^ l/ >. d l/ % 0 =k l/ 2 + s/ lD x] sD
0 sr
[L2 [lA x lB x lC x lD x]x lr 1 + sr lr lc >@] s@ l@ x
'
}

# 上記、prime関数から得られた適当な素数二つが引数です。
# そこから秘密鍵、公開鍵を出力します。
# 例: keygen 10243 19963
keygen ()
{
dc -e "[$1 1 :a]x [$2 2 :a]x [$1 $2 * 3 :a]x"'
[1 ;a]x 1 - [2 ;a]x 1 - * 2 / 1 + S2
[l2 lr [d la :k]x / [la :p]x la 1 + sa l. x] sA
[[la 1 - ;k]x n [ ] n [la 1 - ;p]x n [ ] n [3 ;a]x p sg] s.
1 sa l2 v s^ 2 sr
[l2 lr % 0 =A lr 1 + sr lr l^ !<B] sB lB x
'
}
0718名無しさん@お腹いっぱい。2015/06/06(土) 17:44:29.67
# 上記、keygenが出力した鍵から適当な一段を使い暗号化し、出力します。
# 例:
# keygen 10243 19963
# > 7 14603629 204481009
# > 17 6013259 204481009
# > 119 859037 204481009
# encrypt 859037 204481009 暗号化するfile >暗号化した後のfile
encrypt ()
{
echo 8 o $( printf "8 i %d 12 i $1 $2 | n [ ] n " $( od -vt oC -A n $3 ) ) |dc
}

# 上記の公開鍵で暗号化したものを、秘密鍵で復号します。秘密鍵は上記の例で暗号化した場合、
# 以下の組み合わせになります。
# encrypt 119 204481009 暗号化されたfile >復号化した後のfile
decrypt ()
{
printf "8 i %d 12 i $1 $2 | P " $( cat $3 ) |dc
}
0719名無しさん@お腹いっぱい。2015/06/06(土) 20:13:54.61
ごめんなさい。素数と素数をかけた数が512以下だと復号に失敗します。
0720名無しさん@お腹いっぱい。2015/06/06(土) 20:27:58.37
# 以下じゃなくて未満か。

# 他に、確認に使ったprogram.
# ずるしてopensslを使っています。

# まず!!!!!!!!復号化するfileに値を入れて下さい!!!!!!!!!!!!!。小さいfileが良いと思います。
# mktempで作るfileは自動では削除しません。最初にechoで出力するので手動でお願いします。

# primeで適当な素数を二つ選択しkeygenを行い、そこで作られた鍵で暗号化したfileを
# 復号できるかの確認です。
# 使い方。
# check_2 $( prime 10000 20000 )

# 出力は、出力した時に確認したkeygenに使った素数二つ,暗号化復号化に使える数字と法です。
0721名無しさん@お腹いっぱい。2015/06/06(土) 20:29:33.71
file=
file_encrypt=$( mktemp )
file_decrypt=$( mktemp )
echo 後で削除する事、$file_encrypt $file_decrypt
check_2 ()
{
test $# -lt 2 && return

p1=$( echo $@ |tr ' ' '\n' |sed -n $(( $( openssl rand 2 \
|od -t u -A n ) % $# + 1 ))p )
while # 使いました!!!
p2=$( echo $@ |tr ' ' '\n' |sed -n $(( $( openssl rand 2 \
|od -t u -A n ) % $# + 1 ))p )
test $p2 -eq $p1
do :
done

f ()
{
test $# -eq 0 && return
encrypt $(( $# % 2 ? $1 : $2 )) $3 $file >$file_encrypt
decrypt $(( $# % 2 ? $2 : $1 )) $3 $file_encrypt >$file_decrypt
diff $file $file_decrypt && echo 成功。keygen $p1 $p2, $1 $2 $3 \
|| echo 失敗。keygen $p1 $p2, $1 $2 $3 1>&2
shift 3
f $@
}
f $( keygen $p1 $p2 )

check_2 $( echo $@ |tr ' ' '\n' |grep -vE "($p1|$p2)" )
}
# rm $file_encrypt $file_decrypt
0722名無しさん@お腹いっぱい。2015/06/06(土) 20:36:41.36
もっと大きい値で確認する場合は、
opensslのrandの値も変える必要があったような気がします。もう忘れました。
現在対したコメント無くてごめんなさい。
0723名無しさん@お腹いっぱい。2015/06/07(日) 19:13:41.49
>>715 から sed も取り除いてみました
printf '%s + %s - %s * %s / ' '0 0' 0 1 1 "$@" 'p quit' | dc

>>716-722 力作ですなぁ
072410人に1人はカルトか外国人2015/06/08(月) 17:47:19.33
●マインドコントロールの手法●

・沢山の人が偏った意見を一貫して支持する
 偏った意見でも、集団の中でその意見が信じられていれば、自分の考え方は間違っているのか、等と思わせる手法

・不利な質問をさせなくしたり、不利な質問には答えない、スルーする
 誰にも質問や反論をさせないことにより、誰もが皆、疑いなど無いんだと信じ込ませる手法

偏った思想や考え方に染まっていたり、常識が通じない人間は、頭が悪いフリをしているカルト工作員の可能性が高い

靖国参拝、皇族、国旗国歌、神社神道を嫌うカルト

10人に一人はカルトか外国人

「ガスライティング」で検索を!
0725名無しさん@お腹いっぱい。2015/06/08(月) 21:12:33.56
forの中で
find /foo -iname "123foo.txt" -o -iname "foo.txt"
をしたくて、"123foo.txt" から"foo.txt"を
作りたいのですけどいい方法を教えていただけないでしょうか?
123は0桁から4桁あります。
よろしくお願いします。
0726名無しさん@お腹いっぱい。2015/06/08(月) 22:27:29.53
「シェル 数値 ゼロ梅」でぐぐれ
0727名無しさん@お腹いっぱい。2015/06/08(月) 23:04:24.58
シェルっていうと、おじさんたちが激怒になるから気をつけな
0728名無しさん@お腹いっぱい。2015/06/09(火) 00:33:36.94
「シェルっていうと」じゃなくて「シェルクリプトのことをシェルっていうと」だ
>>726の場合は問題ない
0729名無しさん@お腹いっぱい。2015/06/09(火) 01:25:54.94
$ filename1=123foo.txt
$ filename2=$(echo $filename1 | tr -d [0-9])
$ echo $filename2
foo.txt
0730名無しさん@お腹いっぱい。2015/06/09(火) 01:49:15.59
数字の部分が必ずファイル名の先頭にかたまって出現するということなら
$ filename=123foo.txt
$ echo ${filename##*[0-9]}
foo.txt
0731名無しさん@お腹いっぱい。2015/06/09(火) 08:44:03.74
そうか
trか変数展開をつかうのか
自分は今まで何考えてたんだ
コマンド、変数展開を使いこなせてないことを痛感した
ありがとう
0732名無しさん@お腹いっぱい。2015/06/11(木) 16:47:01.72
いくつかのディレクトリにあるファイルすべてを一括処理してやろうと
foundfiles=$(find /hoge/hoge1 /foo/foo1 -name -type f *.txt)
for x in "${foundfiles}"
do
処理
done
としてみたのですが、うまくいきませんでした。
どこを直せばよいのでしょうか?
0733名無しさん@お腹いっぱい。2015/06/11(木) 17:10:28.24
-nameの引数の位置
0734名無しさん@お腹いっぱい。2015/06/11(木) 18:04:07.93
うわぁー、ばかなことやっちまってた
foundfiles=$(find /hoge/hoge1 /foo/foo1 -name *.txt -type f)
for x in "${foundfiles}"
do
処理
done
これでokですか?まだ、怪しいとこありますか?
0735名無しさん@お腹いっぱい。2015/06/11(木) 18:13:25.03
findの結果と処理のところにecho入れて
気体通りになってるか確認して終わり
かまう奴はアホか
0736名無しさん@お腹いっぱい。2015/06/11(木) 19:55:03.20
優しいんですね
0737名無しさん@お腹いっぱい。2015/06/12(金) 12:06:31.64
foundfiles=$(find /hoge/hoge1 /foo/foo1 -name *.txt -type f)
for x in "${foundfiles}"
do
echo "$x"
done

とやると一見上手くいったように見えましたが、

foundfiles=$(find /hoge/hoge1 /foo/foo1 -name *.txt -type f)
for x in "${foundfiles}"
do
echo "${x##*/}"
echo "$x"
done
としてやると、初めのファイルのファイル名だけ出てきて、あとは検索結果が表示されるだけでした。
なにがまずかったのですか?直すことはできるのでしょうか? 👀
Rock54: Caution(BBR-MD5:0be15ced7fbdb9fdb4d0ce1929c1b82f)
0738名無しさん@お腹いっぱい。2015/06/12(金) 13:33:39.96
ダブルクォートはどんなときに使えばいいのかどんなときに使わないのか
そのあたりがわかってないみたい
がんばれ
0739名無しさん@お腹いっぱい。2015/06/12(金) 14:39:13.27
"${foundfiles}"のダブルクォートを外したらできました。

なんでなんだろう?
for x in "$@"
というのをよく見かけるからまねしてました。

"${foundfiles}"は検索結果を1つの文字列にする。
なら、"$@"は?あれれ?
どういうことなのでしょうか?
0740名無しさん@お腹いっぱい。2015/06/12(金) 14:43:19.06
シェルスクリプトの本でも一冊買ってきてまじめに勉強しろ
そうしない身に付かない
0741名無しさん@お腹いっぱい。2015/06/12(金) 14:49:36.84
find の結果を使って何かするなら、for while xargs findのexec 等を使うけど、
for で変数に入れて回す場合、IFSに改行をセットして、区切ってもらうために変数をクォートはしない

#!/bin/sh -x
var='
a b c d e
2OrMoreSpaces between the words
x y z
'

IFS='
'

# for i in "${var}"
for i in ${var}
do
 echo "=> $i <="
done

応援するよ。がんばって
07427412015/06/12(金) 15:27:47.27
>>6 E.1 を中心に、man bsh、man dash で学習

□E. 学習用テキスト
1. Bourne Shell自習テキスト ( 1993年 ) pdf お薦め



一応、引用しといた
man dash
@ Expands to the positional parameters, starting from one.
  When the expansion occurs within double-quotes, each posi‐
  tional parameter expands as a separate argument. If there
  are no positional parameters, the expansion of @ generates
  zero arguments, even when @ is double-quoted. What this
  basically means, for example, is if $1 is “abc” and $2 is
  “def ghi”, then "$@" expands to the two arguments:
    "abc" "def ghi"

$1 が "abc"で、$2 が "def ghi" のとき、"$@" は "abc" "def ghi" に展開される
0743名無しさん@お腹いっぱい。2015/06/12(金) 15:31:58.73
読みなおしてよかったよ man bsh なんて

訂正 man bash、man dash
0744名無しさん@お腹いっぱい。2015/06/13(土) 13:45:25.05
ありがとう
ネット上の記述とmanで今までなんとかこなせてたけど
基本がないとだめですね
早速、>>6を読んでみます
0745名無しさん@お腹いっぱい。2015/06/13(土) 20:52:58.13
>>739
foundfiles=( $(find /hoge/hoge1 /foo/foo1 -name *.txt -type f) ) ←配列にする
for x in "${foundfiles[@]}"

でおk
0746名無しさん@お腹いっぱい。2015/06/15(月) 13:27:36.31
ありがとう
それでできました
()はコマンド置換だけじゃないんですね
0747名無しさん@お腹いっぱい。2015/06/15(月) 13:44:30.60
コマンド置換は $( )
0748名無しさん@お腹いっぱい。2015/06/15(月) 23:58:45.64
$() で思い出したけど
-----------------------
#!/bin/bash

LAST=0

function test() {
LAST=$1
echo $LAST
}

echo "LAST=$LAST"
test 111
echo "LAST=$LAST"
x=$(test 222)
echo "LAST=$LAST x=$x"
--------------------------
を実行すると

LAST=0
111
LAST=111
LAST=111 x=222 ←なぜ LASTが 222に変更されないのか?

実際は関数のネストとかでもっと複雑だったんだが、
変な動作するようになってデバッグに苦労した・・・
0749名無しさん@お腹いっぱい。2015/06/16(火) 00:33:43.81
えっ? 釣り?
0750名無しさん@お腹いっぱい。2015/06/16(火) 00:48:56.39
サブシェルで実行されるから
0751名無しさん@お腹いっぱい。2015/06/17(水) 12:27:35.75
>>745
スペース入りファイル名に未対応、失格。
0752名無しさん@お腹いっぱい。2015/06/17(水) 13:55:31.31
>>751
では模範解答をどうぞ
0753名無しさん@お腹いっぱい。2015/06/17(水) 20:41:26.36
IFS_tmp=$IFS; IFS=$’\n’
0754名無しさん@お腹いっぱい。2015/06/17(水) 21:21:37.47
改行入りファイル名に未対応、失格。
0755名無しさん@お腹いっぱい。2015/06/17(水) 21:25:36.37
最終模範解答

IFS_tmp=$IFS; IFS=$"\n"
0756名無しさん@お腹いっぱい。2015/06/18(木) 05:55:23.84
改行入りファイル名に未対応、失格。
0757名無しさん@お腹いっぱい。2015/06/18(木) 07:35:13.14
スペース等だけじゃなく、アスタなどの特殊記号にも未対応、失格。
0758名無しさん@お腹いっぱい。2015/06/18(木) 07:48:16.57
そんなファイルは作らなければ解決。
0759名無しさん@お腹いっぱい。2015/06/18(木) 10:04:59.96
だったら全部""でくくっておけばいいでないの?
0760名無しさん@お腹いっぱい。2015/06/18(木) 10:17:46.54
find ... -exec ... +
を避ける理由は?
0761名無しさん@お腹いっぱい。2015/06/23(火) 21:09:03.45
find -print0 | xargs -0
でスペースや改行の入ったファイル名もOKだよね
unix仕様のファイル名の終端はNULLだったっけ?
0762名無しさん@お腹いっぱい。2015/06/24(水) 07:32:33.60
>>761 パイプとプロセスが無駄
find ... -exec ... +
を避ける理由は?
0763名無しさん@お腹いっぱい。2015/06/24(水) 15:25:39.96
>>762
それ使うのは初心者で、逆に実行効率が悪くなる。
0764名無しさん@お腹いっぱい。2015/06/24(水) 15:43:54.58
>>763
理由は?
0765名無しさん@お腹いっぱい。2015/06/24(水) 15:44:35.63
-execだと見つかったファイルの数だけプロセスつくるんだよね?
xargsだとexecシステムコールの引数個数制限までは1個のプロセス作ってその引数に見つかったファイル全部渡すのかな?
0766名無しさん@お腹いっぱい。2015/06/24(水) 15:53:10.35
>>765
> find ... -exec ... +
これの最後の+の意味調べないで、言いがかりつけてんの?
0767名無しさん@お腹いっぱい。2015/06/24(水) 20:58:37.54
さすがに恥ずかしくて逃げ出したか。
0768名無しさん@お腹いっぱい。2015/06/26(金) 03:14:09.55
mvとかで使えない中途半端なもの出されてドヤ顔されてもなあ
0769名無しさん@お腹いっぱい。2015/06/26(金) 08:16:34.16
逃げ出さなかったメンタルだけは褒めてあげよう。
find . -exec sh -c 'mv "$@" hoge' {} +
今度は逃げ出すかな?
0770名無しさん@お腹いっぱい。2015/06/26(金) 08:48:53.03
>>769
それ、1番目に見つかったファイル(ディレクトリ)のみ取りこぼすバグあり。

find . -exec sh -c 'mv "$@" hoge' DUMMY {} +
DUMMYが必要。
0771名無しさん@お腹いっぱい。2015/06/26(金) 09:07:10.65
何だよ、そのDUMMYって。意味ねーどころか、エラー出るし。

xargsと比べてって事だから、省略したけど、.を避けるのはfindでやるんだろ。
あえてやるなら
find . -exec sh -c 'shift; mv "$@" hoge' {} +

xargs押しのベテランさんはどうするんだろう?
初心者に教えてくださいな。
0772名無しさん@お腹いっぱい。2015/06/26(金) 09:11:18.72
>>769
プロセスが無駄とか言っておきながらsh使うってバカなの?
しかもファイル数に比例した分だけ起動するから、一つで済むxargs以下じゃん。やっぱりバカだろ。
0773名無しさん@お腹いっぱい。2015/06/26(金) 09:21:57.94
>>771
オマエ、DUMMYの意味わかってないのか。
shiftしたら逆だぞ、引数「2個」取りこぼす。

shiftの逆(そんなのないけど)をやる必要があるんだよw
0774名無しさん@お腹いっぱい。2015/06/26(金) 09:31:47.52
>>771
$ sh -c 'echo "$@"' 1 2 3 4
2 3 4


↑なぜ 1 が消えるかわかるかな?

$ sh -c 'echo "$@"' DUMMY 1 2 3 4
1 2 3 4

↑DUMMYを入れると 1 を取りこぼさないねw
0775名無しさん@お腹いっぱい。2015/06/26(金) 11:33:10.48
>>772
ベテラン(老害ともいう)登場。
おじいちゃんが現役時代のfindはそうだったらしいけど、今のfindはもっとお利口なんだよ。
おじいちゃんが現役だったころは
find ... -exec ..... \;
だっただろ。今は
find ... -exec ..... +
ってやるんだよ。

>>773-774 これはスマンかった。これだね
| sh -c string [name [arg ...]]

でも、shiftは$1以降に対して働くから
> shiftしたら逆だぞ、引数「2個」取りこぼす。
キミもわかってないね。
■ このスレッドは過去ログ倉庫に格納されています