Командная строка Linux
Шрифт:
– rwxr-xr-x 1 me me 224 2011-10-29 18:44 /home/me/bin/foo
< ls ... /home/me/foo.txt > ? y
– rw-r--r-- 1 me me 0 2012-09-19 12:53 /home/me/foo.txt
Эта команда ищет файлы с именами, начинающимися со строки foo, и для каждого найденного файла выполняет команду ls -l. Операция -ok запрашивает подтверждение у пользователя, прежде чем выполнить команду ls.
Увеличение эффективности
Каждый раз, когда обнаруживается файл, соответствующий критериям, операция -exec запускает новый экземпляр указанной команды. Но иногда желательно
ls -l файл1
ls -l файл2
предпочтительнее было бы выполнить команду:
ls -l файл1 файл2
Здесь команда выполняется только один раз, а не несколько. Существует два способа добиться этого: традиционный, с использованием внешней команды xargs, и альтернативный, с использованием новой возможности в самой команде find. Обсудим сначала альтернативный способ.
Если заменить завершающий символ точки с запятой знаком «плюс», в команде find активируется функция объединения результатов в список аргументов для вызова единственного экземпляра требуемой команды. Вернемся к нашему примеру. Команда:
find ~ -type f -name 'foo*' -exec 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
будет вызывать ls для каждого найденного файла. Изменив команду, как показано ниже:
find ~ -type f -name 'foo*' -exec 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
мы получим тот же результат, но система выполнит команду 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 ~ -iname '*.jpg' -print0 | xargs --null ls -l
Этот прием гарантирует правильную обработку любых имен файлов, даже содержащих пробелы.
Возвращаемся в песочницу
Пришло время применить find для решения некоторых практических (почти) задач. Сначала создадим песочницу с множеством файлов и каталогов:
[me@linuxbox ~]$ mkdir -p playground/dir-{00{1..9},0{10..99},100}
[me@linuxbox ~]$ 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. Давайте найдем их:
[me@linuxbox ~]$ find playground -type f -name 'file-A'
Обратите внимание, что, в отличие от ls, find возвращает результаты в несортированном порядке. Порядок определяется организацией устройства хранения. Мы можем убедиться, что действительно имеем 100 файлов с именем file-A:
[me@linuxbox ~]$ find playground -type f -name 'file-A' | wc -l
100
А теперь выполним поиск файлов по времени их последнего изменения. Этот подход можно использовать для создания резервных копий или организации файлов в хронологическом порядке. Для этого сначала создадим эталонный файл, время последнего изменения которого будет использоваться для сравнения:
[me@linuxbox ~]$ touch playground/timestamp
Эта команда создаст пустой файл timestamp и установит время его последнего изменения равным текущему времени. Мы можем убедиться в этом, использовав еще одну полезную команду, stat, которую можно рассматривать как своего рода форсированную версию ls. Команда stat выводит всю информацию о файле и его атрибутах, которой обладает система: