12

Если я наберу:

ls source/*

source/fonts:
fontello

source/images:
bg1.png                eng.png        fra.png   

Я получаю список файлов, сгруппированных по именам папок. Как я могу просто получить список имен файлов?

ls source/*

source/fonts/fontello
source/images/bg1.png
source/images/eng.png
source/images/fra.png   

Спасибо

3 ответа3

13

Кажется, это невозможно без изменения выходных данных, но есть простой альтернативный способ:

find source/ -type f

Или (специфично для GNU find), чтобы получить файлы только на глубине вашего вопроса:

find source/ -type f -mindepth 2 -maxdepth 2

(или если вы хотите каталоги, которые вам дает ls , удалите -type f)

5

Вы можете просто придерживаться ls, если добавите некоторые psychedlics (ls -d):

# mkdir test
# cd test
# mkdir A B C
# touch {A,B,C}/file*
# ls -d */*    
A/file  B/file  C/file
3

Вас может заинтересовать « 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\}'
    

    который удаляет строки , содержащие три или более / символов.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .