将多个目录传递给 find 中的 -prune 选项

cha*_*dra 12 directory find array arguments

我正在使用find定位和删除备份文件,但希望从搜索中排除某些目录。备份文件名可能会终止.bckbak~,或backup

只有三个要排除的目录的最小工作示例 (MWE) 代码是:

#! /bin/bash
find . -type d \( -path "./.*" -o -path "./Music" -o -path "./Documents" \) -prune -o -type f \( -name "*.bck" -o -name "*.bak" -o -name "*~" -o -name "*.backup" \) -print0 | xargs -0 --no-run-if-empty trash-put
Run Code Online (Sandbox Code Playgroud)

语法\( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -prune似乎有点笨拙,特别是如果有大约十个目录要排除,尽管我在 MWE 中只显示了三个。

是否有更优雅的方法使用输入文件(带有排除目录的列表)或类似数组或类似列表的构造,可以将其压入服务中?

我很抱歉在我写原始问题时没有更明确。

注意:trash-put是一种将文件移动到Trashcan而不是删除它们的实用程序[1]。

[1]。https://github.com/andreafrancia/trash-cli

Jam*_*oon 9

-path ... -prune使用-o() 逻辑传递多个由括号组合在一起的逻辑\( ... \)

find /somepath \( -path /a -prune -o \
                  -path /b -prune -o \
                  -path /c -prune \
               \) \
               -o -print
Run Code Online (Sandbox Code Playgroud)

该示例不会迭代 、 和 处或下的目录或/somepath/a文件。/somepath/b/somepath/c


这是一个使用多个表达式和复杂-exec操作的人为示例。这会打印 Linux 主机上纯文件的文件路径和校验和,修剪主要包含瞬态文件或字符设备的路径

$ find / \( -path /dev -prune -o \
            -path /proc -prune -o \
            -path /sys -prune \
         \) \
         -o -type f \
            -printf '%p ' -exec sh -c 'md5sum -- "{}" | cut -f1 -d" "' \;
/etc/services 00060e37207f950bf0ebfd25810c19b9
/etc/lsb-release f317530ede1f20079f73063065c1684e
/etc/protocols bb9c019d6524e913fd72441d58b68216
/etc/rsyslog.conf 8f03326e3d7284ef50ac6777ef8a4fb8
...
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 6

使用 GNU find(即在非嵌入式 Linux 或 Cygwin 下),您可以-regex将所有这些-path通配符组合成一个正则表达式。

find . -regextype posix-extended \
     -type d -regex '\./(\..*|Music|Documents)' -prune -o \
     -type f -regex '.*(\.(bck|bak|backup)|~)' -print0 |
xargs -0 --no-run-if-empty trash-put
Run Code Online (Sandbox Code Playgroud)

在FreeBSD或OSX,使用-E代替-regextype posix-extended


ter*_*don 5

据我所知,没有选择告诉find从文件中读取模式。一个简单的解决方法是将我想要排除的模式保存在一个文件中,然后将该文件作为反向grep. 例如,我创建了以下文件和目录:

$ tree -a
.
??? a
??? .aa
??? .aa.bak
??? a.bck
??? b
??? .dir1
?   ??? bb1.bak
??? dir2
?   ??? bb2.bak
??? b.bak
??? c
??? c~
??? Documents
?   ??? Documents.bak
??? exclude.txt
??? foo.backup
??? Music
    ??? Music.bak
Run Code Online (Sandbox Code Playgroud)

如果我理解你正确地张贴的例子,你要移动a.bck.aa.bakb.bakc~foo.backupdir2/bb2.bak垃圾桶,休假.aa.bak.dir1/bb1.bakDocuments/Documents.bakMusic/Music.bak他们在哪里。因此,我创建了exclude.txt包含以下内容的文件(您可以添加任意数量的内容):

$ cat exclude.txt 
./.*/
./Music
./Documents
Run Code Online (Sandbox Code Playgroud)

我使用./.*/是因为我理解您的原始发现意味着您要移动.foo当前目录中的隐藏备份文件 ( ),但排除隐藏目录 ( .foo/bar) 中的任何备份文件。所以,我现在可以运行find命令并用于grep排除不需要的文件:

$ find . -type f | grep -vZf exclude.txt | xargs -0 --no-run-if-empty trash-put
Run Code Online (Sandbox Code Playgroud)

Grep 选项:

   -v, --invert-match
          Invert  the  sense  of matching, to select non-matching
          lines.  (-v is specified by POSIX.)
   -f FILE, --file=FILE
          Obtain patterns from FILE, one  per  line.   The  empty
          file  contains  zero  patterns,  and  therefore matches
          nothing.  (-f is specified by POSIX.)
   -Z, --null
          Output a zero byte (the ASCII NUL character) instead of
          the  character  that normally follows a file name.  For
          example, grep -lZ outputs a zero byte after  each  file
          name  instead  of the usual newline.  This option makes
          the output unambiguous, even in the  presence  of  file
          names  containing  unusual  characters  like  newlines.
          This  option  can  be  used  with  commands  like  find
          -print0,  perl  -0,  sort  -z,  and xargs -0 to process
          arbitrary file names, even those that  contain  newline
          characters.
Run Code Online (Sandbox Code Playgroud)