如何从文件名绝对路径数组中获取文件名

如何从文件名绝对路径数组中获取文件名

我有一个 shell 脚本,需要从 /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:经典 Shell 脚本)

如果您想处理该参数的所有单独成员,则需要一个循环。

变体 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每次迭代都会缩短参数列表。

相关内容