1

Я хочу удалить файлы, которые имеют размер = 0. Итак, я попробовал:

find ./ -size 0 | xargs rm

Но у него есть проблема с файлами, имена которых начинаются с пробела. Я нашел это:

find ./ -size 0 -exec rm -i {} \;

Оно работает. Я думаю, что мой путь с xargs слишком сложен для этого.

Что значит {} \; средства?

Не могли бы вы объяснить мне? Мой английский не очень хорош, поэтому, пожалуйста, пишите просто.

4 ответа4

6

{} имеет абсолютно никакого смысла для bash , поэтому передается без изменений в качестве аргумента выполняемой команде, здесь find .

С другой стороны ; имеет особое значение для bash . Обычно он используется для разделения последовательных команд, когда они находятся в одной командной строке. Здесь обратный слеш в \; используется для предотвращения интерпретации точки с запятой как разделителя команд bash а затем для передачи ее в качестве параметра базовой команде, find . Цитируя точку с запятой, то есть ";" или ';' , мог бы быть альтернативным способом оставить его необработанным.

Команда:

find ./ -size 0 -exec rm -i {} \;

означает: найти в текущем каталоге (обратите внимание, что / здесь бесполезен, в любом случае . не может быть, кроме каталога) что-либо, имеющее размер 0, и для каждого найденного объекта выполните команду rm -i name , то есть в интерактивном режиме для каждого запроса. файл, если вы хотите удалить его. {} заменяется каждым именем файла, найденным в выполненной команде. Приятной особенностью является то, что это имя файла является строго одним аргументом, независимо от имени файла (даже содержащего встроенные пробелы, табуляции, переводы строк и любые другие символы). Это не было бы в случае с xargs , если не используются непереносимые хаки. Финал ; есть, чтобы закончить предложение -exec . Причина, по которой его конец должен быть разделен, заключается в том, что другие условия find могут следовать за -exec , хотя это делается редко.

Одна из проблем с этой командой заключается в том, что она не будет игнорировать не простые файлы, поэтому может предложить пользователю удалить сокеты, блочные и символьные устройства, каналы и каталоги. С последним он всегда потерпит неудачу, даже если вы ответите «да».

Другая проблема, хотя и не очень важная, заключается в том, что rm будет вызываться для каждого файла с нулевым размером. Если вы подставите -exec заканчивающийся на /; to + , find оптимизирует создание подпроцесса, вызывая rm только минимально возможное количество раз, часто только один раз.

Вот как я мог бы изменить эту команду:

find . -type f -size 0 -exec rm -i {} +
3

При использовании find -exec {} раскрывается для каждого найденного результата.

Например, если у вас есть example каталога, содержащий 3 файла:a.txt , b.txt и c.txt , find example/ -exec rm -i {} \; будет расширяться до:

find example/ -exec rm -i example/a.txt \;
find example/ -exec rm -i example/b.txt \;
find example/ -exec rm -i example/c.txt \;

\; в конце просто сбежал ; чтобы указать конец шаблона exec. В противном случае это будет интерпретировано самой оболочкой.

0

В сочетании с параметром find команды exec часть {} заменяется именем файлов, найденных при выполнении команды. \; тоже важно, потому что именно это определяет конец выполняемой команды

Например

find ~ -name \*.bak -exec -rm -f {} \;

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

xargs берет стандартные входные строки, обычно из канала, и формирует из них хвостовую часть аргументов при выполнении команды, которую вы ей даете

0

Рассматривать каждый случай по очереди:

xargs

Эта программа добавляет каждую строку из ввода в качестве параметра к любой команде, переданной в качестве своего собственного параметра, а затем запускает результирующую команду, поэтому, если команда find перечисляет три файла a , b и c в текущем каталоге, она выдаст их в качестве вывода :

./a
./b
./c

Если это передано в xargs rm , то эта команда будет выполнена:

rm ./a ./b ./c

Однако, если find также находит файл с именем " d e " , то выполненная команда становится:

rm ./a ./b ./c ./ d e 

Чтобы справиться с этим, find предоставляет опцию -print0 , которая добавляет нулевой символ (\0) после каждого файла вместо обычной новой строки. Чтобы сообщить xargs что входные данные находятся в этой форме, добавьте параметр -0 , поэтому введите команду:

find . ... -print0|xargs -0 rm

соберет и выполнит команду:

rm "./a" "./b" ."/c" "./ d e "

Это будет работать со всеми именами файлов, включая имена, содержащие пробелы, табуляции и новые строки.

find -exec

Когда вызывается эта опция, то для каждого найденного файла выполняется то, что следует (до \;). Это не очень полезно, если только нет средств для ссылки на найденный в данный момент файл, и именно это и делает {} . Его можно вызывать более одного раза в строке выполнения, например, для копирования выбранных файлов в каталог резервного копирования:

find . ... -exec cp "{}" "/BackUp/{}" \;

Это в приведенном выше примере find будет выполняться по очереди:

cp "./a" "/BackUp/./a"
cp "./b" "/BackUp/./b"
cp "./c" "/BackUp/./c"

Обратите внимание, что вне использования в команде find , { и } имеют специальные значения в bash (несколько команд и раскрывающиеся списки), но они включают другие символы в скобках: строка {} копируется буквально, поэтому не требует экранирования.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .