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 пропускает их.
Итак, правильная реализация, аналогичная файлу . -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 и различных побочных эффектов, проверка каждого варианта занимает много времени. Поскольку find
является золотым стандартом в мире POSIX по подсчету файлов в дереве, для меня важно делать то же самое в Python.
Так есть ли эквивалент find2perl
, который можно использовать для Python? До сих пор я просто использовал find2perl
, а затем вручную переводил код Perl.Это сложно, потому что операторы тестирования файлов Perl временами отличаются от файловых тестов Python в os.path.