Как пометить каталоги в выводе команды `find `?

Решение, в чем-то похожее на решение Марка , но не требующее изменений в /etc/fstabили монтирования и размонтирования файловых систем:

#!/bin/sh

lockdir=/tmp/file-copy.lock

if ! mkdir "$lockdir"; then
   echo 'File copy already in progress' >&2
   exit 1
fi

trap 'rmdir "$lockdir"' EXIT

PATH=$PATH:/usr/local/bin

rsync -ai...

Несколько замечаний по этому поводу:

  1. mkdir— атомарная операция, очень похожая на mount, которая завершится ошибкой, если каталог уже существует, но создаст каталог, если его нет. Это безопаснее, чем сначала проверять блокировку файла , а затем создавать его (в два этапа с возможностью состояния гонки в -между ).

  2. Ловушка EXITгарантирует, что каталог блокировки будет удален при завершении сценария. Каталог блокировки также будет удален при перезагрузке (системой ), поскольку он находится в /tmp.

  3. Я установил PATHв соответствующее значение, а не вызывал rsyncс его полным путем. Это чисто косметическая вещь, но она может быть полезна, если позже скрипт будет расширен для использования других команд из набора портов OpenBSD (, таких как resticилиborgbackup).

  4. Опция -zдля rsyncнеобходима только при очень медленных сетевых подключениях (, когда сжатие/распаковка данных выполняется быстрее, чем пропускная способность сети ), и никогда для локального копирования. Я также предпочитаю-i(--itemize-changes)вместо -v(--verbose), так как это точно скажет мне, почему файл был передан.

Для безопасного резервного копирования больших объемов данных я обычно рекомендую использовать специально написанное программное обеспечение для резервного копирования поверх rsync, напримерresticилиborgbackup. Эти два дополнительно выполняют дедупликацию и шифрование данных, а borgbackupможет дополнительно выполнять сжатие. resticхорош в том смысле, что позволяет сохранять резервные копии на внешний сервер (поверх, например. sftp), даже если на этом сервере не установлено restic, тогда как borgbackupтребует, чтобы программное обеспечение было установлено в целевой системе. И restic, и borgbackupуправляют блокировкой хранилища резервных копий.

12
30.05.2021, 20:53
5 ответов

Печать типа файла вместе с именем с помощью-printf "%y %p\n":

$ sudo find. -name 'example.com*' -printf "%y %p\n"
d./archive/example.com
f./renewal/example.com.conf
d./live/example.com

Использование -printfпредполагает, что GNUfind(является наиболее распространенной findреализацией в системах Linux ).

35
28.07.2021, 11:28

Я бы назвал lsна нем:

# find. -name example.com\* -print0 | xargs -0 ls -ld

Если вам нужно выполнить findи lsкак root, а вы этого не делаете, вы можете сделать:

# sudo bash -c "find. -name example.com\* -print0 | xargs -0 ls -ld"

Количество обратных косых черт перед звездочкой *может зависеть от вашей оболочки -возможно, вам нужно 0 или 1 из них внутри кавычек "".

4
28.07.2021, 11:28

Вы можете использовать fileтак:

sudo find. -name "example.com*" -print0 | xargs  -0 sudo file

Пример вывода:

$ sudo find.  -name "example.com*"   -print0 | xargs  -0 sudo file
./example.com. big file: ASCII text
./example.com-dir:       directory
./example.com:           empty
7
28.07.2021, 11:28

Найди дважды:

echo 'directories'
find. -name 'example.com*'   -type d

echo 'non-directories'
find. -name 'example.com*' ! -type d

Обратите также внимание на цитирование шаблона, используемого для проверки имени. Без кавычек оболочка попытается сопоставить строку с именами в текущем каталоге перед вызовом find. Если параметр оболочки failglobбыл установлен в оболочке bashили если параметр оболочки NOMATCHв zshне был отключен, шаблон подстановки без кавычек, который ничему не соответствует, вызовет ошибку оболочки, и findвообще не будет вызываться.


В качестве альтернативы можно просто вывести косую черту в конце пути к каталогу (так ls -pбудет представлять каталоги):

find. -name 'example.com*' \( -type d -exec printf '%s/\n' {} \; -o -print \)

Приведенная выше команда findсначала проверяет правильность имени. Если это так и это каталог, он вызывает printfдля вывода пути к каталогу с косой чертой в конце. Если это не каталог, -printиспользуется для вывода пути как есть.

В GNU findбит -exec printf '%s/\n' {} \;можно заменить на -printf '%p/\n'.

Со стандартным findвы также можете использовать -exec printf '%s/\n' {} +для вызова внешней утилиты printfкак можно меньше раз, но это будет означать, что каталоги, скорее всего, будут выводиться последними или, по крайней мере, в пакетном режиме.


Другая альтернатива состоит в том, чтобы фактически использовать ls -p, чтобы отличить каталоги от других типов файлов. При использовании ls -pкаталог будет указан с завершающим символом /, как и выше.

find. -name 'example.com*' -exec ls -f -d -p {} +

Здесь я использую -f, чтобы не позволить lsсортировать вывод, и -d, чтобы избежать вывода содержимого каталогов.

Вы можете использовать ls -Fвместо ls -p, чтобы поставить другие метки для типов файлов, отличных от каталогов. Например, исполняемые файлы будут иметь суффикс *, а символические ссылки будут иметь суффикс @.

И -p, и -F(, и -f, и-d)являются стандартными опциями утилиты ls.

24
28.07.2021, 11:28

Если вам нужен более портативный вариант, который будет работать с *вариантами nix без опции gnu -printf(macOS, например ), вы можете добавить косую черту в конец пути к каталогу через lsвот так:

find. -name "example.com*" -exec ls -dF {} \;

пример:

$ sudo find. -name "example.com*" -exec ls -dF {} \;
./archive/example.com/
./renewal/example.com.conf
./live/example.com/

Это также оказалось в формате, более подходящем для дальнейшей передачи в большее количество команд unix.

2
28.07.2021, 11:28

Теги

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