ファイル名絶対パス配列からファイル名を取得する方法

ファイル名絶対パス配列からファイル名を取得する方法

/ 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繰り返すたびに引数リストが短くなります。

関連情報