Ответ 1
Быстрые решения
$ ls | perl -lne 'print if stat && -f _' 1 2 3 4 5 file1 $ ls | perl -lne 'print if lstat && -f _' file1
Символьные ссылки и поиск
По умолчанию GNU find
никогда не вызывает различий или не следует за символическими ссылками, но в документации find
описаны переключатели, которые меняют эту политику.
Параметры, управляющие поведением ссылок по ссылкам, следующие: -
-P
find
не разыгрывает символические ссылки вообще. Это поведение по умолчанию. Эта опция должна быть указана перед любым из имен файлов в командной строке.
-H
find
не вызывает разыгрывание символических ссылок (за исключением случаев, когда имена файлов в командной строке разыменовываются). Если символическая ссылка не может быть разыменована, используется информация для самой символической ссылки. Эта опция должна быть указана перед любым из имен файлов в командной строке.
-L
find
где возможно, разыменовывают символические ссылки, и там, где это невозможно, они используют свойства самой символической ссылки. Эта опция должна быть указана перед любым из имен файлов в командной строке. Использование этой опции также подразумевает то же поведение, что и параметр-noleaf
. Если вы позже используете опции-H
или-P
, это не отключает-noleaf
.
-follow
Этот параметр является частью "выражения" и должен указываться после имен файлов, но в остальном он эквивалентен-L
. Опция-follow
влияет только на те тесты, которые появляются после нее в командной строке. Этот параметр устарел. По возможности вам следует использовать-L
.
Преобразование команд find в Perl
Стандартное распространение поставляется с утилитой find2perl
, которая совместима с find
от старых систем Unix.
$ find2perl . -type f | perl ./file1
Вместо этого мы можем запросить файлы, которые являются либо обычными файлами, либо ссылками на простые файлы.
$ find2perl . -follow -type f | perl ./1 ./2 ./3 ./4 ./5 ./file1
В коде find2perl
создается, по умолчанию wanted
sub, переданное в find
из модуля File:: Find
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
-f _
&& print("$name\n");
}
но с -follow
, получим
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = stat($_)) &&
-f _
&& print("$name\n");
}
Обратите внимание, что единственное отличие заключается в том, что wanted
вызывает stat
или lstat
, где последний задокументирован как
lstat EXPR
lstat
То же самое, что и функция
stat
(включая установку специального дескриптора файла_
), но статирует символическую ссылку вместо укажите символические ссылки. Если символические ссылки не реализованы в вашей системе, выполняется нормальноеstat
. Более подробную информацию см. В документации дляstat
.Если EXPR опущен, укажите
$_
.
Как показывает результат выборки из find2perl
, вы можете выразить свое намерение с помощью оператора filetest, но уточните семантику символических ссылок с вашим выбором stat
по сравнению с lstat
.
Этот забавный _
токен
_
на концах приведенных выше быстрых решений - это специальный дескриптор файла, который упоминается в lstat
документации. Он содержит копию последнего результата от stat
или lstat
, чтобы избежать необходимости многократно выполнять эти дорогостоящие системные вызовы. Операторы Filetest, такие как -f
, -r
, -e
и -L
также заполняют этот буфер:
Если какой-либо из тестов файла (или оператора
stat
илиlstat
) задан специальным дескриптором файла, состоящим из одиночной подчеркивания, то структура stat предыдущего теста файла (или оператораstat
) является используется, сохраняя системный вызов. (Это не работает с-t
, и вам нужно помнить, чтоlstat
и-L
оставляют значения в структуре stat для символической ссылки, а не реального файла.) (Также, если буфер статистики был заполнен по вызовуlstat
-t
и-B
будет reset с результатамиstat _
). Пример:print "Can do.\n" if -r $a || -w _ || -x _; stat($filename); print "Readable\n" if -r _; print "Writable\n" if -w _; print "Executable\n" if -x _;