лучший способ получить вывод стиля «найти» из «ls -fR»

avatar
Jerry Fan
8 августа 2021 в 21:50
75
1
0

Моя цель — найти самый быстрый способ вывести список всех доступных файлов в каталоге (назовем его главным каталогом). Главный каталог содержит около 5 миллионов файлов, организованных с использованием подкаталогов, но неясно, как устроены подкаталоги. После некоторых исследований я понял, что самый быстрый способ сделать это — использовать ls -fR (-f отключает сортировку)

Вывод по умолчанию из ls -fR примерно такой:

$ ls -fR dir1
dir1:
.  subdir1  ..

dir1/subdir1:
.  file1  ..

Мой желаемый вывод — результат, полученный с помощью find (хотя поиск занимает в два раза больше времени):

$ find dir1/ -type f
dir1/subdir1/file1

Хотя я потенциально могу разобрать результат ls -fR, мне интересно, есть ли простой способ сделать вывод ls -fR в стиле "найти". Я надеюсь, что есть очень простой переключатель, и я просто не замечаю его

Источник
rturrado
8 августа 2021 в 21:54
0

@JerryFan Попробуйте ls -fR -p | grep -v / как сказано в: askubuntu.com/a/811236/1025976

chepner
8 августа 2021 в 21:55
3

Что нужно сделать со списком файлов? Вы почти наверняка должны написать программу, которая перебирает файловую систему, а не пытаться анализировать вывод find или ls.

Stephen C
8 августа 2021 в 23:51
2

Что ж, я думаю, что реальное решение состоит в том, чтобы не неоднократно перечислять все 5 миллионов файлов. Вместо этого сделайте это один раз и поместите результаты в базу данных (или даже в плоский файл), к которой вы сможете обращаться. (5 миллионов файлов в неорганизованной структуре похоже на то, что происходит, когда кто-то не обучает группу аспирантов и RA правильному управлению файлами. По крайней мере, ваши 5 миллионов файлов не находятся в HSM ...)

user1934428
9 августа 2021 в 08:24
0

@JerryFan: у вас есть неявное ограничение (-type f), что вас интересуют только простые файлы, а не каталоги. ls не может этого сделать. Кроме того, ls может вызвать у вас проблемы, если один из файлов содержит в своем имени символ новой строки. Возможно, вы могли бы также показать контекст, как вы собираетесь использовать создаваемый список имен файлов?

Socowi
9 августа 2021 в 08:54
0

@StephenC Это именно то, что делает locate.

Stephen C
9 августа 2021 в 09:43
0

@Socowi - тогда вы должны упомянуть об этом в своем ответе!

Socowi
9 августа 2021 в 12:09
0

Я уже упоминал об этом.

Ответы (1)

avatar
Socowi
8 августа 2021 в 22:42
1

поиск занимает вдвое больше времени

Интересно. Вы действительно уверены?

  • ls -fR игнорирует скрытые файлы и каталоги. Возможно, ls просто пропускает часть работы. Попробуйте также ls -fRA.
  • Если вы запустите find; ls -fR, последний будет иметь огромное преимущество благодаря кэшированию. Попробуйте поменять порядок или очистить кеш (sync; echo 3 | sudo tee /proc/sys/vm/drop_caches) перед каждой командой.

Надеюсь, есть очень простой переключатель, и я просто не замечаю его

Не то чтобы я знал. В Posix ls такого точно нет. Насколько я могу судить по man ls, даже GNU ls 8.32 не имеет такой опции.

Вы можете адаптировать вывод ls, чтобы он соответствовал результату find, используя

ls -fRpA | awk '/:$/ {sub(/:$/,"/"); p=$0; next} length() && !/\// {print p $0}'

Несмотря на то, что это приведет к поломке файлов/каталогов с разрывами строк и файлов, оканчивающихся на :. Кроме того, вы немного замедлите работу скрипта. Я предполагаю, что чем длиннее пути, тем медленнее он становится. Это также может частично объяснить, почему find медленнее, чем ls. Первый просто печатает намного больше текста, потому что ему приходится снова и снова повторять название каталогов верхнего уровня.

Настоятельно не рекомендую использовать приведенный выше скрипт. Он хрупкий и нечитаемый, вероятно, только ради преждевременной оптимизации: Наверняка вы хотите что-то сделать с напечатанным списком. Это что-то, вероятно, займет больше времени, чем создание списка. Кроме того, с разными реализациями, работающими в разных системах, find может быть быстрее, чем ls — никогда не знаешь наверняка.

Кроме того, не анализируйте вывод ls/find, вместо этого используйте find -exec для выполнения реальной задачи. Если вам действительно нужно, find -print0 будет безопасным вариантом (можно заменить на find -exec printf %s\\0 {} +, если он недоступен в вашей системе).

В зависимости от задачи locate может быть быстрой альтернативой find. Если нет, попробуйте распараллелить find с помощью чего-то вроде printf %s\\0 ./* | xargs -0 -I_ -P0 find _ -type f или инструмента, такого как fd со встроенным распараллеливанием.