Да, есть несколько способов сделать это с помощью команды find
. Я перечислю некоторые из них в том порядке, который мне кажется важным для понимания в вашей ситуации.
Похоже, что ваш скрипт принимает несколько аргументов имени файла, поэтому наиболее эффективный и почти универсальный способ сделать это с помощью команды find
следующий:
find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
Это выполнит ваш скрипт с максимально возможным количеством найденных аргументов имени файла. Ваш скрипт будет вызван несколько раз, если это необходимо для обработки всех имен файлов. Обратите внимание на +
в конце строки.
Это оригинальный и наиболее универсальный метод. Он менее эффективен для вашей ситуации, поскольку вызывает perl
один раз для каждого найденного файла. Это использование было доступно с самых ранних дней Unix. Обратите внимание на экранированное двоеточие (\;
) в конце строки (в отличие от +
выше).
find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
До -exec ... +
синтаксис был добавлен к find
, команда xargs
была изобретена для повышения эффективности обработки списков имен файлов или других аргументов. Она работает почти так же, как -exec ... +
пример выше:
find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
Если ваша реализация поддерживает это, вы должны использовать опцию -print0
в find
, вместе с -0
аргументом xargs
. Это заставляет find
печатать нулевые символы между строками аргументов и предотвращает xargs
от разделения аргументов по чему-либо, кроме нулевого символа. Это помогает предотвратить xargs
от неправильного разделения аргументов в случае, если имена файлов содержат пробелы или другие специальные символы.
Использование -exec ... +
в целом является лучшей идеей, поскольку find
помещает имена файлов непосредственно в список аргументов вашего сценария, исключая процесс и избегая любой интерпретации, которая может произойти при передаче по трубопроводу в xargs
. Однако xargs
может иметь преимущества, если вам нужно больше контроля над процессом. Смотрите страницу xargs
man.
Вы также можете проверить команду find2perl
, которая принимает те же аргументы, что и find
, и печатает perl
программу для выполнения тех же действий. Затем вы можете включить сгенерированный perl
код в свой сценарий. В сгенерированном ниже сценарии вы измените предпоследнюю строку, чтобы вызвать вашу функцию вместо print
.
$ find2perl foo -type f -name \*.txt # /*
#[часть кода преамбулы удалена для краткости]
# Обход нужных файловых систем
File::Find::find({wanted => \&wanted}, 'foo');
exit;
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
-f _ &&
/^.*\.txt\z/s
&& print("$name\n");
}
Пропустил установить xserver-xorg-legacy
и поставить:
allowed_users=anybody
needs_root_rights=yes
в /etc/X11/Xwrapper.conf
.