我有一个 shell 脚本,用于查找文件/tmp/bbsnode1
,如果该文件存在,则将其删除。我想做的是,如果存在多个文件(/tmp/bbsnode2
、/tmp/bbsnode3
和/tmp/bbsnode4
),则删除所有文件。但仅当它们全部存在时才删除它们。
这是我到目前为止所拥有的:
if [ -f /tmp/bbsnode1 ]
then
/usr/bin/rm /tmp/bbsnode1
fi
答案1
我会使用外壳功能为此,而不是脚本:
rm-all-or-none() {
for f; do
[ -f "$f" ] ||
{ printf '%s is not an existing file, no files removed\n' "$f" >&2
return 1;}
done
rm -fv -- "$@"
}
然后我会使用大括号扩展来调用它,而不是 glob。 Glob 只扩展到以下文件存在,但在这种情况下,我们想要指定文件并且仅在以下情况下删除它们:全部其中存在:
rm-all-or-none /tmp/bbsnode{1..4}
更长的等效版本:
rm-all-or-none() {
for f in "$@"; do
if [ -f "$f" ]; then
:
else
printf '%s is not an existing file, no files removed\n' "$f" >&2
return 1
fi
done
rm -fv -- "$@"
}
另请参阅:
答案2
您可以使用任意命令,例如ls
检查文件并在一行中删除它们
ls /tmp/bbsnode{1,2,3,4} &>/dev/null && rm /tmp/bbsnode{1,2,3,4}
请注意,通常在 /tmp 中执行此类操作是不安全的,因为任何其他用户都可能创建具有相同名称的冲突文件。
简短的解释:
如果其中一个文件不存在,则返回值ls
非零。 is{1,2,3,4}
大括号扩展:它扩展为每个数字的字符串:所以/tmp/bbsnode{1,2,3,4}
与 相同/tmp/bbsnode1 /tmp/bbsnode2 /tmp/bbsnode3 /tmp/bbsnode4
。&&
仅当前一个命令的返回值为零时,才会执行下一个命令,因此这里仅rm
当所有 4 个文件都存在时才执行。最后,&> /dev/null
抑制输出ls
(&>
重定向stdout
和stderr
,/dev/null
摆脱它)。
下面是另一个仅包含 shell 内置函数的解决方案。它与其他人的回答类似,但没有额外的函数或脚本:
set -- /tmp/bbsnode{1,2,3,4}
(for f; do test -f "$f" || exit; done) && rm -- "$@"
答案3
在这种特殊情况下,你可以这样做:
set -- file[1-4]
[[ $# -eq 4 ]] && rm -f -- "$@"
这是与、或1set
中任何一个匹配的文件名的参数列表,然后仅当参数数量等于 4(即所有文件都存在)时才显示这些文件。 file1
file2
file3
file4
rm
1:为了简单起见,我使用file
而不是/tmp/bbsnode
答案4
您可以使用这个脚本,名为removing_group
#!/usr/bin/bash
function check {
while (( "$#" )) ; do
if [ -f "$1" ] ; then
# echo "The file $1" ;
shift ;
else
# echo "The's no file $1";
return 1
fi
done
return 0
}
if check $@; then
while (( "$#" )) ; do
# echo "Remove $1" ;
rm "$1" ;
shift ;
done
fi
该check
函数检查所有参数是否为常规文件。如果下一个文件不存在,该函数将返回1
并且不会发生任何事情。如果所有文件都存在,则返回的0
将是 process if check $@
,这将一一删除文件。用于检查和删除的文件在命令行中描述为参数,例如
./removing_group /tmp/bbsnode1 /tmp/bbsnode2 /tmp/bbsnode3 /tmp/bbsnode4
或者
./removing_group /tmp/bbsnode{1,2,3,4}