我有一个 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
每次迭代都会缩短参数列表。