This question already has an answer here:
这个问题已经有了答案:
- How do I pass a wildcard parameter to a bash file 2 answers
- 如何将通配符参数传递给bash文件2答案
So as the title describes, I want to recursively delete all files which match a naming pattern given by the user, but only if the file is empty. Here is my attempt:
正如标题所描述的,我想递归地删除所有符合用户给定命名模式的文件,但前提是文件为空。这是我的尝试:
#!/bin/bash
_files="$1"
[ $# -eq 0 ] && { echo "Usage: $0 filename"; exit 1; }
[ ! -f "$_files" ] && { echo "Error: $0 no files were found which match given naming structure."; exit 2; }
for f in $(find -name $_files)
do
if [ -s "$f" ]
then
echo "$f has some data."
# do something as file has data
else
echo "$f is empty. Deleting file."
rm $f
fi
done
Example output:
示例输出:
./remove_blank.sh *.o*
./Disp_variations_higher_0.o1906168 has some data.
./remove_blank.sh *.e*
./Disp_variations_higher_15.e1906183 is empty. Deleting file.
As you can see, the code works, but only for one file at a time. Should be a relatively simple fix to get it to work, but I extremely new to bash scripting and can't seem to figure it out. Sorry for the noobish question. I did some research to find an answer but didn't find exactly what I needed. Thanks in advance for any help.
正如您所看到的,代码可以工作,但每次只针对一个文件。应该是一个相对简单的解决方案,但我对bash脚本编程非常陌生,而且似乎无法解决它。不好意思,我想问个没礼貌的问题。我做了一些调查来寻找答案,但没有找到我真正需要的。谢谢你的帮助。
Edit I have found two different solutions to the problem. As @David Z's suggestion, one can fix this by 1st deleting the Error checking part of the script as well as putting quotes around the $_files variable in the find function. Then the code looks like this:
编辑我找到了两种不同的解决方法。正如@David Z的建议,我们可以通过删除脚本的错误检查部分以及在find函数中为$_files变量加上引号来解决这个问题。代码是这样的:
#!/bin/bash
_files=$1
[ $# -eq 0 ] && { echo "Usage: $0 filename"; exit 1; }
for f in $(find -name "$_files")
do
做
if [ -s $f ]
then
echo "$f has some data."
# do something as file has data
else
echo "$f is empty. Deleting file."
rm $f
fi
done
完成
Or, one can also simply change the for loop to for f in "$@", which allows the error check to be kept in the script. I am not sure which method is better but will update again if I find out.
或者,也可以简单地将for循环改为“$@”中的f,这样就可以在脚本中保留错误检查。我不确定哪种方法更好,但如果我发现了,我会再次更新。
1 个解决方案
#1
2
It looks like the way you're invoking the script, the shell expands the pattern before running your script. For example, in
它看起来像您调用脚本的方式,shell在运行脚本之前扩展模式。例如,在
./remove_blank.sh *.o*
the shell converts *.o*
to the list of filenames that match that pattern, and then what it actually runs is something like
shell将*。o*到匹配该模式的文件名列表,然后它实际运行的是类似的内容
./remove_blank.sh Disp_variations_higher_0.o1906168 other_file.o12345 ...
But you only check the first argument in your script, so that's the one that winds up getting deleted.
但是您只检查脚本中的第一个参数,所以这是最终被删除的参数。
Solution: quote the pattern when you run the script.
解决方案:在运行脚本时引用模式。
./remove_blank.sh '*.o*'
You will also need to remove the test [ ! -f "$_files" ] ...
because $_files
is being set to the pattern (such as *.o*
), not a filename. In fact, you might want to rename the variable to make that clear. And finally, you need to quote the variable in your find
command,
您还需要删除测试[!- f“带有_file美元”)…因为$_files被设置为模式(例如*.o*),而不是文件名。实际上,您可能希望重命名该变量以使其更清晰。最后,需要在find命令中引用变量,
... $(find -name "$_files") ...
so that the pattern makes it all the way through to find
without being converted into filenames by the shell.
这样一来,这个模式就可以在不被shell转换为文件名的情况下,找到它。
There are some other issues with the script but you might want to ask about those on Code Review. What I've identified here is just the minimum needed to get it working.
这个脚本还有一些其他的问题,但是您可能想要询问关于代码评审的问题。我在这里指出的是使它工作所需要的最小值。
Incidentally, you can accomplish this whole task using find
itself, which will at least give cleaner code:
顺便说一句,你可以使用find本身来完成整个任务,它至少会提供更清晰的代码:
find -name "$_files" -type f -empty -delete
#1
2
It looks like the way you're invoking the script, the shell expands the pattern before running your script. For example, in
它看起来像您调用脚本的方式,shell在运行脚本之前扩展模式。例如,在
./remove_blank.sh *.o*
the shell converts *.o*
to the list of filenames that match that pattern, and then what it actually runs is something like
shell将*。o*到匹配该模式的文件名列表,然后它实际运行的是类似的内容
./remove_blank.sh Disp_variations_higher_0.o1906168 other_file.o12345 ...
But you only check the first argument in your script, so that's the one that winds up getting deleted.
但是您只检查脚本中的第一个参数,所以这是最终被删除的参数。
Solution: quote the pattern when you run the script.
解决方案:在运行脚本时引用模式。
./remove_blank.sh '*.o*'
You will also need to remove the test [ ! -f "$_files" ] ...
because $_files
is being set to the pattern (such as *.o*
), not a filename. In fact, you might want to rename the variable to make that clear. And finally, you need to quote the variable in your find
command,
您还需要删除测试[!- f“带有_file美元”)…因为$_files被设置为模式(例如*.o*),而不是文件名。实际上,您可能希望重命名该变量以使其更清晰。最后,需要在find命令中引用变量,
... $(find -name "$_files") ...
so that the pattern makes it all the way through to find
without being converted into filenames by the shell.
这样一来,这个模式就可以在不被shell转换为文件名的情况下,找到它。
There are some other issues with the script but you might want to ask about those on Code Review. What I've identified here is just the minimum needed to get it working.
这个脚本还有一些其他的问题,但是您可能想要询问关于代码评审的问题。我在这里指出的是使它工作所需要的最小值。
Incidentally, you can accomplish this whole task using find
itself, which will at least give cleaner code:
顺便说一句,你可以使用find本身来完成整个任务,它至少会提供更清晰的代码:
find -name "$_files" -type f -empty -delete