В Perl есть прекрасная небольшая утилита под названием find2perl, которая переводит (довольно точно) командную строку для утилиту Unix find
в сценарий Perl, чтобы сделать то же самое.
Если у вас есть такая команда find:
find /usr -xdev -type d -name '*share'
^^^^^^^^^^^^ => name with shell expansion of '*share'
^^^^ => Directory (not a file)
^^^ => Do not go to external file systems
^^^ => the /usr directory (could be multiple directories
Он находит все каталоги, заканчивающиеся на share
ниже /usr
Теперь запустите find2perl /usr -xdev -type d -name '*share'
, и он выдаст Perl-скрипт, который сделает то же самое. Затем вы можете изменить сценарий для своего использования.
В Python есть os.walk()
, который, безусловно, имеет необходимую функциональность, рекурсивный список каталогов, но есть большие различия.
Рассмотрим простой случай find . -type f -print
, чтобы найти и распечатать все файлы в текущем каталоге. Наивная реализация с использованием os.walk()
выглядела бы так:
for path, dirs, files in os.walk(root):
if files:
for file in files:
print os.path.join(path,file)
Однако это приведет к другим результатам, чем при вводе find . -type f -print
в оболочке.
Я также тестировал различные циклы os.walk () против:
# create pipe to 'find' with the commands with arg of 'root'
find_cmd='find %s -type f' % root
args=shlex.split(find_cmd)
p=subprocess.Popen(args,stdout=subprocess.PIPE)
out,err=p.communicate()
out=out.rstrip() # remove terminating \n
for line in out.splitlines()
print line
Разница в том, что os.walk () считает ссылки как файлы; find пропускает их.
Таким образом, правильная реализация, аналогичная file . -type f -print
, становится:
for path, dirs, files in os.walk(root):
if files:
for file in files:
p=os.path.join(path,file)
if os.path.isfile(p) and not os.path.islink(p):
print(p)
Поскольку существуют сотни вариантов основных вариантов поиска и различных побочных эффектов, проверка каждого варианта занимает много времени. Поскольку find
является золотым стандартом в мире POSIX по подсчету файлов в дереве, для меня важно делать то же самое в Python.
Так есть ли эквивалент find2perl
, который можно использовать для Python? До сих пор я просто использовал find2perl
, а затем вручную переводил код Perl. Это сложно, потому что операторы проверки файлов Perl отличаются, чем файл Python иногда проверяет в os.path.