重複の可能性:
ファイルとディレクトリの名前を繰り返し変更します。
私は次のスクリプトを書いた。
#!/bin/bash
SAVEIFS=$IFS
alias export='export'
IFS=$(echo -en "\n\b")
find $1 -name "*" -a -type f -exec sh -c let len=`expr length {}` \; -exec sh -c let str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {} $str.mp3 \;
# restore $IFS
unalias export
IFS=$SAVEIFS
質問:
複数のシェルから変数を別のシェルにエクスポートできないことがわかっているので、次のことが必要です。
変数の使用
実行シェルを使用しないでください
ではどうすればいいですか?
次のスクリプトを実行するとき:
find $1 -name "*" -a -type f -exec let len=`expr length {}` \; -exec let str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {} $str.mp3 \;
# Note : above script doesn't has 'sh -c'
次のエラーが発生します。
find: `let': No such file or directory
エクスポート、削除export、またはletでテストしましたが、-exec組み込みシェルコマンドで誤った点が見つかりました....!
どんなアイデアがありますか? ? ? ?
答え1
注意すべき点がいくつかあります。
二重引用符は、変数の内容がシェルで解釈されるのを防ぎます。 IFSにはデフォルトで「space + tab + newline」を含めることができるため、
NEWIFS=IFS
NEWIFSに何も配置できない可能性があります。SAVEIFS="$IFS" ... IFS="$(echo -en "\n\b")" #yes, you can have " inside $( ... ) : the shell will gladly interpret them by # order of depth inside the $() construct. # A big advantage over using backquotes where it would get mixed up and almost unreadable ... IFS="$SAVEIFS"
変数名に予約語を使用しないでください(
for
let
などを避けてください)。また、多くの「共通」変数名(例:など)も避けLINES
てくださいCOLUMNS
。export
なぜニックネームなのかexport
?シェルが古くなったり、せいぜい役に立たない場合、これはループを生成する良い方法のようです。精度は、
-name *
で終わるすべてを避けることを意味します.
。-exec sh ....
これはサブシェルから始まりますsh
。 shが呼び出しシェルで終了すると、宣言されたすべての変数は失われます。
次のようなものが必要です。
#!/bin/bash
for adirectory in "$@" ; do
find "$adirectory" -type f -name '*.3gp' -print | while IFS= read -r wholeline ; do
mylength=$(echo "$wholeline" | wc -c) #Not needed, just kept as exemple of a way to achieve it
myfilewithoutext="$(echo "$wholeline" | sed -e 's/.3gp$//' )"
#keeps only the filename without its ".3gp" or ".3GP" extension.
ffmpeg -y -i "$wholeline" "${myfilewithoutext}.mp3" > /dev/null #? please check if it works
done #end of the find|while
done #end of the for looping on all the arguments passed to the script (dir names)
IFS
while IFS= read -r wholeline ; do
通話中にのみ空の文字列に設定されますread -r wholeline
。外側は手が届かなかった。コマンドパラメータは、その値が一時的に設定されたVAR="something" command parameters
状態で呼び出されます。ここではIFSを何も設定していません。それでも1行ずつ渡され、空なので、行全体を読みます。VAR
something
''
IFS
read wholeline
答え2
コメントによると(*.3gpを*.mp3に変換):
for n in *.3gp; do
ffmpeg -y -i "$n" "${n%.3gp}.mp3"
done
Olivierのコメントによると、ファイル名をエスケープする必要がない場合(つまり、スペースやワイルドカードが含まれていない場合)、サブディレクトリのファイルでも機能します*.3gp
。または(bashに入れて)使用できます。$(find ...)
\[?*
**/*.3gp
shopt -s extglob
.bashrc