枚举文件 *.pdf 排除 *_book.pdf

枚举文件 *.pdf 排除 *_book.pdf

如何枚举目录中的所有文件并按模式排除。

例如:所有 *.pdf 排除 *_book.pdf。我尝试这样做:

for $PDF in $(ls *.pdf | grep -v *_book.pdf);
do
   echo "File $PDF"
done

这是个好办法吗?还有其他方法吗?如果声明或其他。

答案1

不要ls在脚本中使用。

此外,在循环中声明的变量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

相关内容