Вас может заинтересовать « find
бедняка»:
shopt -s globstar
shopt -s
s етсь названный вариант оболочки (s).
Опция globstar
определяется в bash (1) следующим образом:
Если установлено, шаблон **
используемый в контексте расширения имени файла / пути, будет соответствовать файлам [sic] и нулю или более каталогов и подкаталогов.
Если за шаблоном следует символ /
, совпадают только каталоги и подкаталоги.
Итак, после того, как вы сделали shopt -s globstar
, выполните любую из следующих команд:
ls -d1 -- source/** # The character after the ‘d’ is the digit one.
ls -d -- source/** | cat # i.e., it will write that into a pipe to any command.
printf "%s\n" source/**
будет производить вывод:
source/
source/fonts
source/fonts/fontello
source/images
source/images/bg1.png
source/images/eng.png
source/images/fra.png
К сожалению, это включает и имена каталогов.
Это может помочь вам немного узнать,
printf "%s\n" source/**/
будет производить вывод:
source/
source/fonts
source/images
т.е. только имена каталогов.
Вы можете перенаправить вывод одной из первых наборов команд в один файл, перенаправить вывод вышеуказанного во второй файл, а затем использовать comm
, diff
или что-то подобное, чтобы вычесть второй файл из первого, оставив только простые файлы (не каталоги). Но не делай этого.
Другой подход (это не намного лучше)
ls -d --file-type -- source/** | grep -v '/$'
Опция --file-type
указывает ls
отображать /
в конце каждого имени каталога (и другие символы в конце других (специальных) типов файлов), например так:
source// # Added an extra one
source/fonts/ # Added one
source/fonts/fontello
source/images/ # Added one
source/images/bg1.png
source/images/eng.png
source/images/fra.png
а затем grep -v '/$'
удаляет строки, заканчивающиеся на /
; т.е. имена каталогов.
К сожалению, опция --file-type
не указана в POSIX. Если ваша версия ls
не поддерживает ее, используйте -F
. Это похоже на --file-type
за исключением того, что оно также отображает *
в конце имен исполняемых файлов, что некоторых людей раздражает.
Вы можете устранить их с помощью sed
:
ls -dF -- source/** | sed -e '/\/$/d' -e 's/\*$//'
Если вы хотите что-то сделать со всеми файлами (и только файлами), вы можете сделать
for f in source/**
do
if [ -f "$f" ]
then
Insert commands to be applied to plain files here.
fi
done
Заметки:
- Когда
ls
выводит на терминал, и он не находится в режиме -l
(l ong), он записывает несколько имен в строке (если имена не очень длинные).
Вы можете заставить его написать по одному имени в строке, указав -1
(один) или перенаправив вывод в файл или канал.
- Вам, вероятно, не нужны команды
--
в ls
поскольку вы указываете каталог, содержимое которого вы создали.
Вы должны использовать его при перечислении *
в неизвестном каталоге, как защита от имен файлов, начинающихся с -
.
- Не пытайтесь анализировать вывод из
ls
.
- Параметр оболочки
globstar
видимому, не определяется POSIX. (На самом деле, я не уверен, что POSIX распознает какие-либо параметры оболочки.)
Хотя это кажется bash
ism, будьте осторожны - он может присутствовать не во всех версиях bash.
Если у fonts
или images
есть подкаталоги, **
перечислит их все, рекурсивно, до конца.
Один (несколько грязный и ненадежный) способ ограничения глубины
ls -d --file-type -- source/** | grep -v '\(/.*\)\{3\}'
который удаляет строки , содержащие три или более /
символов.