Я хочу найти все файлы размером более 100 МБ и старше 20 дней и заархивировать только файлы.TXT и.txt по отдельности

Конечно, я бы использовал стандартный редактор UNIX (!):

for f in ENSG*
do
  printf '1i\n\t%s\n.\nw\nq\n' "$f" | ed -s "$f"
done

Это отправляет небольшой скрипт команд на ed, а именно:

  • в строке 1 вставьте(i)некоторый текст; текст передается через printfкак имя файла, которому предшествует табуляция(\t)
  • после вставки этого текста(.)сохраните файл на диск(w)и закройте(q)

Если действительно количество файлов превышает лимит строки команды -, вы можете использовать команду find; отрегулируйте параметры (начальные каталоги, имена файлов и т. д. )по мере необходимости:

find. -name 'ENSG*' -exec sh -c 'printf "1i\n\t%s\\n.\nw\nq\n" "$1" | ed -s "$1" ' findsh {} \;

Основное решение такое же, но в оболочке того, что я называю «оболочкой поиска»,--findвыполняется sh -c...для каждого (единственного )совпадающего имени файла; строка findshявляется заглушкой для $0, и имя файла передается этой оболочке вместо фигурных скобок {}.Тогда сама оболочка имеет имя файла в качестве параметра $1, так что это то, что используют команды printfи ed.

0
02.07.2021, 08:29
1 ответ

Обратите внимание, что -size +100M, где этот суффикс Mне является стандартным расширением -, выбирает файлы, размер которых строго превышает 100 МБ, 104 857 600 байт, а не 100 МБ (100 000 000 байт ). Для размеров (строго )больше 100 МБ вам потребуется -size +100000000c(, который является стандартным ).

-mtime +20предназначен для файлов, возраст которых составляет 21 день¹ ровно (или был с точностью до наносекунды на момент вызова find)или старше. Вам нужно -mtime +19для файлов старше 20 дней (по крайней мере в POSIX-совместимых реализациях find, не все в этом отношении ).

Предполагая, что вы находитесь в оболочке типа Bourne -, отличной от zsh, оставлять это $HOMEбез кавычек не имеет смысла, так как нет смысла вызывать здесь split+glob. В оболочках POSIX вы также можете использовать ~вместо "$HOME".

zip— не очень Unixy-команда.По умолчанию он сам расширяет подстановочные знаки, поэтому, если у вас есть файл с именем *.txt, zip -m '*.txt.zip' '*.txt'фактически создаст zip-файл со всеми файлами txtв каталоге. Ситуация может ухудшиться, например, если этот файл находится в каталоге с именем *. Вы можете избежать этого с помощью флага -nwили использовать более unix-команду, которая поддерживает этот старый формат zip, например bsdtar.

Если вы сделаете find ~, все пути, переданные в zip, будут абсолютными путями, поэтому в итоге у вас будут zip-файлы, члены которых перечислены с их полными путями(home/you/dir/file.txt... ). Вы можете использовать предикат BSD/GNU-execdirfindили опцию -jдля zip, чтобы избежать этого.

Обратите внимание, что не все реализации findрасширят {}в {}.zip, то есть когда {}не является аргументом -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для лучшего сжатия всех этих файлов одним вызовом xz.


¹ дней здесь 86400 (24 × 60 × 60 )Unix-секунды, а не календарные дни, в которых изменения часов из-за перехода на летнее время не учитываются.

2
28.07.2021, 11:20

Теги

Похожие вопросы