find コマンドの変数と追加のシェルの質問

find コマンドの変数と追加のシェルの質問

重複の可能性:
ファイルとディレクトリの名前を繰り返し変更します。

私は次のスクリプトを書いた。

#!/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

質問:

複数のシェルから変数を別のシェルにエクスポートできないことがわかっているので、次のことが必要です。

  1. 変数の使用

  2. 実行シェルを使用しないでください

ではどうすればいいですか?

次のスクリプトを実行するとき:

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=IFSNEWIFSに何も配置できない可能性があります。

    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)

IFSwhile IFS= read -r wholeline ; do 通話中にのみ空の文字列に設定されますread -r wholeline。外側は手が届かなかった。コマンドパラメータは、その値が一時的に設定されたVAR="something" command parameters状態で呼び出されます。ここではIFSを何も設定していません。それでも1行ずつ渡され、空なので、行全体を読みます。VARsomething''IFSread wholeline

答え2

コメントによると(*.3gpを*.mp3に変換):

for n in *.3gp; do
    ffmpeg -y -i "$n"  "${n%.3gp}.mp3"
done

Olivierのコメントによると、ファイル名をエスケープする必要がない場合(つまり、スペースやワイルドカードが含まれていない場合)、サブディレクトリのファイルでも機能します*.3gp。または(bashに入れて)使用できます。$(find ...)\[?***/*.3gpshopt -s extglob.bashrc

関連情報