分析
スクリプトには対処すべき問題が複数あります。それを一歩一歩見てみましょう:
tempDir=./tmp/
logDir=./logs/
for file in $( find `echo $logDir` -type f )
このスキームは、ファイル名にスペースが含まれていないことを前提としています (これは珍しい制限ではありません。名前にスペースが含まれる問題を回避するのは比較的難しいことです)。また、echo
;は必要ありません。書くだけ:
for file in $(find "$logDir" -type f)
続き:
do
name=eval basename $file
これbasename
により、環境変数name
が値eval
と引数に設定された状態でコマンドが実行されます$file
。ここで必要なものは次のとおりです。
name=$(basename "$file")
名前にスペースを含めることはできないため、二重引用符は厳密には必要ありません (ただし、名前にスペースが含まれることがあるため、すべてのファイル名を引用するのは悪い習慣ではありません)。
echo $name
name が設定されていないため、空白行がエコーされます。
name=$(echo $name | sed 's/.$//')
name が設定されている場合、最後の文字が切り落とされますが、 name が の場合、A
何も残りません。
echo $tempDir
opFile=$tempDir$name
echo $opFile
done
二重引用符を付けるか取るか、_tmp
接尾辞をopFile
に追加していないという事実は、残りに問題はありません。
合成
変更をまとめると、次のようになります。
tempDir=./tmp/
logDir=./logs/
for file in $(find "$logDir" -type f)
do
name=$(basename "$file")
echo "$name" # Debug only
echo "$tempDir" # Debug only
opFile="$tempDir${name}_tmp"
echo "$opFile"
done
これは、すべての中間結果を示しています。それを次のように完全に圧縮できます。
tempDir=./tmp/
logDir=./logs/
for file in $(find "$logDir" -type f)
do
opFile="$tempDir"$(basename "$file")"_tmp"
echo "$opFile"
done
または、名前にスペースが含まれていないため、二重引用符のより単純な組み合わせを使用します。
tempDir=./tmp/
logDir=./logs/
for file in $(find "$logDir" -type f)
do
opFile="$tempDir$(basename $file)_tmp"
echo "$opFile"
done
もちろん、エコーは、実行する予定のコピーまたは移動操作の代理として存在します。
編集: ...そして、スペースとグロビング文字を含むファイル名の制限を削除するには、次のようにします。
tempDir=./tmp/
logDir=./logs/
find "$logDir" -type f |
while IFS= read -r file
do
opFile="${tempDir}${file##*/}_tmp"
echo "$opFile"
done
改行を含むファイル名では失敗します。それを処理したい場合は、find ... -print0 | xargs -0
またはを使用して解決策を調査してくださいfind ... -exec
。