/ tmpディレクトリからファイル名を削除する必要があるシェルスクリプトがあります。ファイル名は、私のスクリプトに渡されたファイル名のリストで検出する必要があります。
./deletetmpfiles.sh /var/moht/test1.pdf /var/shif/log/test4.pdf
必要な数のファイルをパラメータとしてdeletetmpfiles.sh
スクリプトに渡すことができます。
上記の例を考えてみましょう。
私のスクリプトは/tmp/test1.pdf
&を削除する必要があります。/tmp/test4.pdf
以下は私が試したものです。
echo "Deleting the following files as they got printed: $@"
cd /home/system/bey.de/invoices/send4print
if [ $? -eq 0 ]; then
echo "Deleting the following on the server: $@"
echo "rm -f /tmp/$(basename $@)"
rm -f /tmp/$(basename $@)
fi
ただし、/tmpの最初のファイル(例:/tmp/test1.pdf)のみが削除され、残りのファイルは削除されません。
何か提案してもらえますか?
答え1
basename
複数のファイルを処理しません。
名前
basename - strip directory and suffix from filenames
要約
basename NAME [SUFFIX] basename OPTION...NAME...
-a
このオプションを使用しない場合(GNU Coreutils):
-a, --multiple support multiple arguments and treat each as a NAME
ただし、ファイル名に改行文字が含まれると中断されます。
basename -a
パラメータが新しい行で返されるため、コマンドは失敗します。
basename "$@"
foo.pdf
bar.pdf
rm
渡された引数は改行で区切られているため、コマンドは中断されます。
このコードは明らかに問題を解決しました。
rm $(echo "$(basename -a "$@")")
しかし、その効果についてはよくわかりません。
その後、パラメータを繰り返すことができます。
for i in "$@"; do
echo "rm -f /tmp/$(basename "$i")"
rm -f "/tmp/$(basename "$i")"
done
スペースのある名前を処理するには、スクリプトに渡すときに適切にエスケープする必要があります。
$ script.sh "foo bar.pdf"
または
$ script.sh foo\ bar.pdf
答え2
より複雑な内容に進む前に、しっかりとした基本的な知識を持つことをお勧めします。
一般に、与えられたタスクを実行する方法はより多くあります。
あなたの例に関する基本的な質問は、「$@
正確に何を表していますか?」です。
答えは次のとおりです。「すべてのコマンドライン引数は別々の別々の文字列です」(RobbinsとBeebe:Classic Shell Scripting)
パラメーターのすべての個々のメンバーを処理するにはループが必要です。
変形1:
for file in "$@" ; do
echo "Deleting the following on the server: $file"
file=$(basename $file)
echo "rm -f /tmp/$file"
rm -f /tmp/$file
done
変形2:
until [ $# = 0 ]; do
echo "Deleting the following on the server: $file"
file=$(basename $file)
echo "rm -f /tmp/$file"
rm -f /tmp/$file
shift
done
バリアント2では、shift
繰り返すたびに引数リストが短くなります。