如何枚举目录中的所有文件并按模式排除。
例如:所有 *.pdf 排除 *_book.pdf。我尝试这样做:
for $PDF in $(ls *.pdf | grep -v *_book.pdf);
do
echo "File $PDF"
done
这是个好办法吗?还有其他方法吗?如果声明或其他。
答案1
此外,在循环中声明的变量for
不应有美元符号。美元符号插值变量的值;因此$PDF
读作“名为 的变量的当前值PDF
”。
for PDF in *.pdf
do
case $PDF in
*_book.pdf) continue;;
esac
echo "File $PDF"
done
这种case
语法让一些初学者感到害怕,但我更喜欢用它来if
处理这类事情。但如果你喜欢,你可以使用
if [[ $PDF =~ _book\.pdf$ ]]; then
continue
fi
或简写
[[ $PDF =~ _book\.pdf$ ]] && continue
case
另外一个好处是它可以移植到 POSIXsh
甚至是古老的原始 Bourne sh
。
请注意, 中的模式case
是一个 glob,而 中使用正则表达式(因此之前[[ $variable =~ regex ]]
不应该有)。*
_book
答案2
使用shopt -s extglob
(这可能是您系统的默认值,否则请设置它),您可以使用扩展匹配,其中包括否定匹配模式:
# Directry contents
>ls -1
1_book_not.pdf
1_book.pdf
1.pdf
1.txt
# With negative match
>ls -1 !(*_book).pdf
1_book_not.pdf
1.pdf
答案3
您的表达式中存在轻微语法错误for
。请尝试以下操作:
for PDF in $(ls *.pdf | grep -v *_book.pdf);
do
echo "File $PDF"
done
这看上去效果不错。
答案4
另一个选择是使用find
:
find . -maxdepth 1 -name '*.pdf' ! -name '*_book.pdf'
例如,考虑包含以下四个文件的目录:
$ ls
a_book.pdf book.txt nook.pdf not_book1.pdf
现在,运行我们的命令:
$ find . -maxdepth 1 -name '*.pdf' ! -name '*_book.pdf'
./not_book1.pdf
./nook.pdf
怎么运行的
find .
告诉 find 在当前目录中开始搜索。-maxdepth 1
告诉 find 跳过子目录。-name '*.pdf'
告诉 find 查找名称以 结尾的文件.pdf
。! -name '*_book.pdf'
告诉 finds 从输出中排除任何名称以 结尾的文件_book.pdf
。