我在用着
find $HOME -type f -size +100M -mtime +20 -exec zip -m '{}.zip' '{}' \;
该命令正在压缩所有文件。我只想压缩 *.TXT 和 *.txt 文件。知道我们该怎么做吗?
答案1
请注意,-size +100M
如果M
后缀是非标准扩展名,则选择大小严格大于 100MiB(104,857,600 字节)的文件,而不是 100MB(100,000,000 字节)。对于(严格)大于 100MB 的大小,您需要-size +100000000c
(这是标准的)。
-mtime +20
适用于确切 21 天(或find
调用时的纳秒)或更早的文件。您需要-mtime +19
超过 20 天的文件(至少在符合 POSIX 的find
实现中,并非所有都在这方面)。
假设您处于类似于 Bourne 的 shell 中,而不是zsh
,则不加$HOME
引号是没有意义的,因为在这里调用 split+glob 是没有意义的。在 POSIX shell 中,您还可以使用~
代替"$HOME"
.
zip
是一个不太 Unixy 命令。默认情况下,它会自行扩展通配符,因此如果您有一个名为 的文件*.txt
,实际上会创建一个包含该目录中zip -m '*.txt.zip' '*.txt'
所有文件的 zip 文件。txt
如果该文件位于名为 example 的目录中,情况可能会变得更糟*
。您可以使用该-nw
标志来避免这种情况,或者使用支持旧 zip 格式(例如 .zip)的更unixy命令bsdtar
。
如果这样做find ~
,则传递给的所有路径都zip
将是绝对路径,因此最终,您将获得其成员及其完整路径 ( home/you/dir/file.txt
...) 列出的 zip 文件。您可以使用 BSD/GNU-execdir
find
谓词或-j
选项来zip
避免这种情况。
请注意,并非所有find
实现都会扩展{}
in {}.zip
,也就是说,when{}
不是单独存在于 的参数中-exec
。在那些没有的情况下,您需要使用 进行sh
呼叫-exec sh -c 'zip -nw -m "$1.zip" -- "$1"' sh {} ';'
。
要匹配文件名,可以使用-name
谓词。您可以使用'(' -name '*.txt' -o -name '*.TXT' ')'
来匹配txt
或TXT
文件,或者-name '*.[tT][xX][tT]'
在某些find
实现中-iname '*.txt'
还包括Txt
, tXT
... 文件。对于多种find
实现,-name
要求文件名是用户区域设置中的有效文本。由于所有.txtTXT
字符都是可移植字符集的一部分,因此您可以将区域设置修复为 C,以保证它始终匹配以这些字符结尾的文件,即使文件路径的其余部分在用户区域设置中不是有效文本。
所以:
LC_ALL=C find ~ '(' -name '*.txt' -o -name '*.TXT' ')' \
-type f \
-size +100000000c \
-mtime +19 \
-execdir zip -nw -m '{}.zip' -- '{}' ';'
或者使用zsh
和:
for f (~/**/*.(txt|TXT)(ND.L+100000000m+19)) zip -j -nw -m $f.zip $f
请注意,zip 是 80 年代末的一种旧格式,按照今天的标准来看压缩率很低。它唯一的优点是它是 Microsoft 操作系统上唯一支持开箱即用的压缩格式(实际上,它既进行归档又进行压缩,而您在这里只需要后者)。
在这里,如果您不需要与 Microsoft 操作系统的互操作性,您可以使用更现代的压缩器,例如xz
、bzip2
。即使gzip
从 90 年代初开始,它也使用相同的压缩算法,因为zip
它只负责压缩,所以也可以更好地减小大小。所有这些还可以一次压缩多个文件,因此可以使压缩许多文件的过程更加高效,因为您可以更少地调用压缩器。
例如,你可以这样做:
xz ~/**/*.(txt|TXT)(ND.L+100000000m+19)
从zsh
shell 一次调用即可更好地压缩所有这些文件xz
。
^天这里是 86400 (24 × 60 × 60) Unix 秒,不是日历日,因为不考虑夏令时导致的时钟变化。