DE_CopyOldToNew.txt
古いファイル名を新しいファイル名にコピーするための複数のコピーコマンドを含むファイルがあります。
ファイルには次の行が含まれています。
cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
cp /migrationfiles/Company\ Name\ GmbH/2014.139_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.139_NewFile_1.pdf
私のシェルスクリプトでは、各行を繰り返し実行します。
echo "Start!"
while read -r line
do
command "$line"
done < /tmp/DE_CopyOldToNew.txt
スクリプトの実行時に読み取った各行について、次のようになります。
: No such file or directory6: cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
プロンプトで手動で行を実行すると、エラーなしでうまく機能します。
答え1
問題は、行全体を次のように読み取ることです。一つシェル変数をline
選択してから引用符を使用します(例:as "$line"
)。
シェル変数を扱うとき、特にスペースやその他の「問題のある」文字を含むファイル名を処理する場合、二重引用符は通常正確ですが、この場合は次のことを意味します。ワイヤーcp
命令で構成そしてその主張ステートメントは単一のシェルトークンとして扱われますcommand
。
これは、ループでcp
引数/migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf
のあるコマンドを実行せず、/appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
シェルが次の実行可能ファイルを実行しようとしていることを意味します。
cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
コマンドと引数を区別するために使用されるスペースは、コマンド名の一部として解釈されます。もちろん、この実行可能ファイルは存在しません。
あなたができることは、この行を次の3つの変数として読むことです。
echo "Start!"
while read cmd arg1 arg2
do
command "$cmd" "$arg1" "$arg2"
done < /tmp/DE_CopyOldToNew.txt
構造は常に例に示されている形式を取ると仮定します。
ノートこのread
コマンド確かにこの-r
オプションは、次のスペースがエスケープ文字として解釈されるのを無効にするために含まれています\
。ただし、ここでこれを行うにはシェルが必要です。
答え2
あなたは言う、
DE_CopyOldToNew.txt
古いファイル名を新しいファイル名にコピーするための複数のコピーコマンドを含むファイルがあります。
...そしてあなたはこのコマンドを実行したいと言いましたcp
。
ラッキーです。これは、シェルによって順番に実行されるコマンドセットを含むファイルであるシェルスクリプトがあるためです。あなたがすべきことは、シェルにスクリプト内のコマンドを実行させることだけです。
sh DE_CopyOldToNew.txt
これにより、デフォルトのシェルが起動し、sh
ファイルの内容がコマンドごとに実行されます。
答え3
TXTファイルが何もせずにデータソースとして扱うので、スクリプトを使用して実行する必要があるだけでなく、データの制御にも使用できます。
# Read each line of the file
while IFS= read -r line; do
# Get the files using awk with ' /' as separator.
# $line could have escaped spaces with '\ ' so we use parameter substitution →
# → to substitute them to unescaped spaces: "${line//\\ / }".
source_file=$(awk -F' /' '{ print "/"$2 }' <<<"${line//\\ / }") # source file
destination=$(awk -F' /' '{ print "/"$3 }' <<<"$line") # destination
# For example you can control that the source file exists
if [[ ! -f "$source_file" ]]; then
echo "The file $source_file does not exists!"
exit
fi
# The cp command is executed here
cp "$source_file" "$destination"
done </tmp/DE_CopyOldToNew.txt