Bash: ls * без группировки папок

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   

Благодарность

Августин Ридингер
источник
Если это для использования сценариев, вы можете увидеть mywiki.wooledge.org/ParsingLs . (Тем не менее, есть способы использовать findнеправильные, особенно, если вы бежите for file in $(find ...), вы попали в один из них).
Чарльз Даффи

Ответы:

13

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

find source/ -type f

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

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

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

maxxvw
источник
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
ikrabbe
источник
@Cthulhu Хорошо, мой пример слишком короткий, если у вас есть папки в A, B / O C, -d помогает отображать только то, что вы выбрали. Я на самом деле не люблю находить, и вы можете определить глубину по аргументу с помощью ls -d
ikrabbe
Я предложил изменить другой ответ, чтобы ограничить глубину.
o11c
@ o11c очень хорошо, но все еще findжирный зверь.
Икраббе
3

Вы можете быть заинтересованы в «бедняков find»:

shopt -s globstar

shopt -s s ETs именованный параметр оболочки (ы). globstarПараметр определяется следующим образом в Баш (1) :

Если установлено, шаблон, **используемый в контексте расширения имени файла / пути, будет соответствовать файлам [sic] и нулю или более каталогов и подкаталогов. Если за шаблоном следует a /, совпадают только каталоги и подкаталоги.

Итак, после того, как вы сделали shopt -s globstar, любую из следующих команд:

ls -d1 - source / **                  # Символ после 'd' является цифрой один. 
ls -d - источник / ** | cat             # то есть, он запишет это в канал для любой команды. 
printf "% s \ n" источник / **

будет производить вывод:

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 //                             # Добавлен дополнительный 
источник / fonts /                        # Добавлен один
источник / шрифты / fontello
источник / изображения /                       # Добавлен один
источник / изображения / bg1.png
источник / изображения / eng.png
источник / изображения / fra.png

а затем grep -v '/$'удаляет строки, которые заканчиваются /; т.е. имена каталогов. К сожалению, --file-typeопция не указана в POSIX . Если ваша версия lsне поддерживает ее, используйте -F. Это похоже на то, --file-type за исключением того, что он также отображает *в конце имен исполняемых файлов, что некоторые люди считают раздражающим. Вы можете устранить их с помощью sed:

ls -dF -- source/** | sed -e '/\/$/d' -e 's/\*$//'

Если вы хотите что-то сделать со всеми файлами (и только файлами), вы можете сделать

для f в источнике / **
делать
    если [-f "$ f"]
    тогда
        Вставьте команды, которые будут применяться к простым файлам здесь.
    фи
сделано

Примечания:

  • Когда lsвыводится на терминал, и он не находится в режиме -l( l ong), он записывает несколько имен в строке (если имена не очень длинные). Вы можете заставить его написать одно имя в строке, указав -1(один) или перенаправив вывод в файл или канал.
  • Вам, вероятно, не нужны команды --in, lsпоскольку вы выводите каталог, содержимое которого вы создали. Вы должны использовать его при перечислении *в неизвестном каталоге, в качестве защиты от имен файлов, которые начинаются с -.
  • Не пытайтесь анализировать вывод с ls.
  • Опция globstarоболочки, по-видимому, не определяется POSIX. (На самом деле, я не уверен, что POSIX распознает какие-либо параметры оболочки.) Хотя это выглядит как bashism, будьте осторожны - он может присутствовать не во всех версиях bash.
  • Если fontsили imagesимеет подкаталоги, **перечислит их все, рекурсивно, до конца. Один (несколько грязный и ненадежный) способ ограничения глубины

    ls -d --file-type -- source/** | grep -v '\(/.*\)\{3\}'
    

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

Скотт
источник