Добавить в цитаты Настройки чтения

Страница 53 из 113



-rw-r--r-- 1 me   me   0 2012-09-19 12:53 /home/me/foo.txt

мы получим тот же результат, но система выполнит команду ls только один раз.

Тот же результат можно получить с помощью команды xargs. Она принимает входные данные со стандартного ввода и преобразует их в список аргументов для указанной команды. В данном примере ее можно было бы использовать так:

find ~ -type f -name 'foo*' -print | xargs ls -l

-rwxr-xr-x 1 me   me 224 2011-10-29 18:44 /home/me/bin/foo

-rw-r--r-- 1 me   me   0 2012-09-19 12:53 /home/me/foo.txt

Здесь вывод команды find передается по конвейеру команде xargs, которая, в свою очередь, конструирует список аргументов для команды ls и выполняет ее.

ПРИМЕЧАНИЕ

Несмотря на то что в командную строку можно включить большое число аргументов, оно не бесконечно. Не исключена возможность конструирования такой команды, которая окажется слишком велика для командной оболочки. Когда длина командной строки превышает максимально допустимый размер, xargs выполнит указанную команду с максимально возможным числом аргументов и затем повторит процесс, пока не исчерпает все, что получит со стандартного ввода. Чтобы увидеть максимально возможную длину командной строки, выполните xargs с параметром --show-limits.

обработка файлов с необычными именами

Unix-подобные системы позволяют встраивать в имена файлов пробелы (и даже символы перевода строки). Это порождает проблемы при выполнении программ, таких как xargs, конструирующих списки аргументов для других программ. Внутренние пробелы интерпретируются как разделители, и получившаяся команда будет интерпретировать слова, разделенные пробелами, как отдельные аргументы. Для решения этой проблемы find и xarg предлагают использовать в качестве разделителя аргументов пустой символ (null character). В кодировке ASCII пустой символ определен как символ с нулевым кодом (в противоположность пробелу, например, который в кодировке ASCII определен как символ с кодом 32). Команда find поддерживает операцию -print0, которая производит вывод имен файлов, разделенных пустым символом, а команда xargs имеет параметр --null, позволяющий организовать прием значений, разделенных пустым символом. Например:

find ~ -iname '*.jpg' -print0 | xargs --null ls -l

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

Возвращаемся в песочницу

Пришло время применить find для решения некоторых практических (почти) задач. Сначала создадим песочницу с множеством файлов и каталогов:

[[email protected]/* */ ~]$ mkdir -p playground/dir-{00{1..9},0{10..99},100}

[[email protected]/* */ ~]$ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z}

Какая мощь командной строки! Эти две строки создают каталог playground, содержащий 100 подкаталогов и 26 пустых файлов в каждом. Попробуйте-ка то же самое сделать в графическом интерфейсе!

Это волшебство мы сотворили с помощью уже знакомой команды (mkdir) механизма подстановки в командной оболочке (фигурные скобки) и новой команды touch. Объединив команду mkdir с параметром -p (который вынуждает mkdir создать родительские каталоги в указанном пути) с подстановкой фигурных скобок, мы смогли создать 100 каталогов.

Команда touch обычно используется для обновления времени последнего изменения файлов. Но если передать ей имя несуществующего файла, она создаст пустой файл.

В нашей песочнице мы создали 100 файлов с именем file-A. Давайте найдем их:

[[email protected]/* */ ~]$ find playground -type f -name 'file-A'

Обратите внимание, что, в отличие от ls, find возвращает результаты в несортированном порядке. Порядок определяется организацией устройства хранения. Мы можем убедиться, что действительно имеем 100 файлов с именем file-A:

[[email protected]/* */ ~]$ find playground -type f -name 'file-A' | wc -l

100

А теперь выполним поиск файлов по времени их последнего изменения. Этот подход можно использовать для создания резервных копий или организации файлов в хронологическом порядке. Для этого сначала создадим эталонный файл, время последнего изменения которого будет использоваться для сравнения:

[[email protected]/* */ ~]$ touch playground/timestamp

Эта команда создаст пустой файл timestamp и установит время его последнего изменения равным текущему времени. Мы можем убедиться в этом, использовав еще одну полезную команду, stat, которую можно рассматривать как своего рода форсированную версию ls. Команда stat выводит всю информацию о файле и его атрибутах, которой обладает система:

[[email protected]/* */ ~]$ stat playground/timestamp

  File: `playground/timestamp'

  Size: 0          Blocks: 0       IO Block: 4096 regular empty file



Device: 803h/2051d Inode: 14265061 Links: 1

Access: (0644/-rw-r--r--)  Uid: ( 1001/ me)   Gid: ( 1001/ me)

Access: 2012-10-08 15:15:39.000000000 -0400

Modify: 2012-10-08 15:15:39.000000000 -0400

Change: 2012-10-08 15:15:39.000000000 -0400

Если применить команду touch к файлу еще раз и затем исследовать его с помощью stat, мы увидим, что время последнего его изменения обновилось:

[[email protected]/* */ ~]$ touch playground/timestamp

[[email protected]/* */ ~]$ stat playground/timestamp

  File: `playground/timestamp'

  Size: 0          Blocks: 0       IO Block: 4096 regular empty file

Device: 803h/2051d Inode: 14265061 Links: 1

Access: (0644/-rw-r--r--)  Uid: ( 1001/ me)   Gid: ( 1001/ me)

Access: 2012-10-08 15:23:33.000000000 -0400

Modify: 2012-10-08 15:23:33.000000000 -0400

Change: 2012-10-08 15:23:33.000000000 -0400

Далее воспользуемся командой find, чтобы обновить время последнего изменения некоторых файлов в нашей песочнице:

[[email protected]/* */ ~]$ find playground -type f -name 'file-B' -exec touch '{}' ';'

Эта команда обновит время последнего изменения для всех файлов с именем file-B, имеющихся в песочнице. Теперь найдем с помощью find обновленные файлы, сравнив все файлы с эталонным файлом timestamp:

[[email protected]/* */ ~]$ find playground -type f -newer playground/timestamp

В результате мы получим все 100 файлов с именем file-B. Поскольку команда touch применялась ко всем файлм file-B в песочнице после обновления файла timestamp, они оказались «новее», чем timestamp, и потому были идентифицированы проверкой -newer.

В заключение вернемся к проверке плохих разрешений, выполнявшейся выше, и применим ее к каталогу playground:

[[email protected]/* */ ~]$ find playground ( -type f -not -perm 0600 ) -or ( -type d -not -perm 0700 )

199

Эта команда выведет все 100 каталогов и 2600 файлов, хранящихся в playground (а также файл timestamp и сам каталог playground, всего 2702 элемента), потому что ни один из них не соответствует нашему определению «удовлетворительные разрешения». Вооружившись новыми знаниями об операторах и операциях, добавим в эту команду операции для применения новых разрешений к файлам и каталогам в песочнице:

[[email protected]/* */ ~]$ find playground ( -type f -not -perm 0600 -exec chmod 0600

'{}' ';' ) -or ( -type d -not -perm 0700 -exec chmod 0700 '{}' ';' )

Основываясь на повседневном опыте, следует отметить, что намного проще ввести две команды — одну для каталогов и одну для файлов, чем одну большую составную команду, но знание, что можно действовать именно так, вам не помешает. Главное, что вы должны понять, — как можно использовать операторы и операции для решения практических задач.

Параметры

Наконец мы добрались до параметров. Параметры помогают управлять областью поиска. Они могут включаться в выражения команды find наряду с другими проверками и операциями. В табл. 17.8 перечислены наиболее часто используемые параметры.