Як перелічити файли без каталогів та фільтрувати за назвою (ls параметри)


42

У мене називається каталог uploads. Він містить купу файлів, а також кілька підкаталогів, які, в свою чергу, містять файли.

Чи є спосіб я можу (за один крок) зробити наступне:

  1. Перерахуйте ТОЛЬКІ файли у кореневій каталозі завантажень - я не хочу бачити назви підпапок чи їх вміст;

    і

  2. НЕ перераховуйте файли, які починаються з t_

Я знаю про -dпрапор, але він не отримує мене зовсім того, чого я хочу.

Відповіді:


53

Це звучить як робота для find.

  • Використовуйте -maxdepthлише для повернення поточного каталогу, а не повторного пошуку всередині папок
  • Використовуйте -type fлише для повернення файлів, а не каталогів або вузлів пристроїв чи ще чого
  • Використовуйте комбінацію, якщо -notі -nameщоб уникнути файлів з іменами, які ви не хочете

Це може скластись так:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'

Дякую! Я досить новачок у CLI і ніколи раніше не використовував пошук. Я обов'язково загляну далі в це.
EmmyS

2
@EmmyS: Тут ви можете знайти ще одну маленьку хитрість. @Gilles згадав, використовуючи -exec ls -lG -- {} +у своїй відповіді, щоб отримати вихід, використовуючи додаткові параметри до ls. Ви також можете додати -lsцю знахідку лише для швидкого та брудного наближення детального перегляду ls.
Калеб

18

GNU ls (тобто команда ls для невбудованих систем Linux та Cygwin, також доступна для деяких інших уніцій) має можливість приховати деякі файли на основі їх імен. Хоча не можна ігнорувати каталоги.

ls --hide='t_*' uploads

Інший підхід полягає в тому, щоб змусити вашу оболонку зробити відповідність. Bash, ksh і zsh мають заперечувальний зразок, !(t_*)який відповідає всім файлам, крім відповідних t*; в bash цю функцію потрібно ввімкнути shopt -s extglob, а в zsh її потрібно ввімкнути setopt ksh_glob. Zsh також має еквівалентний синтаксис, ^t_*який потрібно ввімкнути setopt extended_glob. Це досі не ігнорує каталоги. Zsh має додаткову функцію, яка дозволяє зіставляти файли не тільки за назвою, але і за метаданими та іншим: глобальні класифікатори . Додайте (.)наприкінці матчу, щоб обмежити звичайні файли. Заперечення ^є частиною синтаксису відповідності імен, тому ^t_*(.)означає "всі звичайні файли не збігаються t_*", а не "всі файли, які не відповідають звичайним файлам t_*".

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Якщо ви опинитесь без вдосконалених інструментів, ви можете це зробити на будь-якому Unix find. Це не та річ, яку ти зазвичай вводиш у командному рядку, але вона потужна та точна. Калеб уже показав, як це зробити за допомогою пошуку GNU . -maxdepthВаріант не є стерпним; ви можете використовувати -pruneзамість цього, щоб портативно зупинитись findвід повторення.

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Замінити -printна , -exec ls -lG -- {} +щоб виконати lsз вашими улюбленими опціонами на файли.

Усі команди вище приховують точкові файли (тобто файли, назва яких починається з а .). Якщо ви хочете їх відобразити, перейдіть -Aдо lsабо додайте Dглобальний класифікатор у zsh ( ls uploads/^t_*(.D)). З find, ви можете використовувати інший підхід, щоб зробити його повторним лише одним рівнем ( findспеціально не розглядає файли крапок). Це повністю працює лише в тому випадку, якщо ви працюєте findв поточному каталозі.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print

3
У вас є денна робота? ;-) Мене постійно дивує довжина та рівень деталей ваших відповідей, навіть до найпростіших запитань тут у Unix SE! .. Продовжуйте це все-таки! :)
alex

Дякую! Чудова деталь. Я не знаю, чи є у мене зараз «передові інструменти» чи ні; Я на Mac на роботі (хоча Linux вдома, тому я впевнений, що це стане в нагоді в якийсь момент).
EmmyS

@EmmyS: Для вашого Linux-коробки моє використання -maxdepthмає працювати, але проблема "переносимості", до якої звертається Гілл, полягає в тому, що BSD find(який я також знаходимо на OSX, я думаю) - трохи інша тварина, тому вам може знадобитися і його відповідь. @Gilles: +1 за трюк zsh!
Калеб

1
@Gilles: Деякі не такі соковиті коментарі щодо prunes приходять до тями, але я відпущу це, просто кажучи, що коли я обмінюю свої власні системи, скільки разів думка " працювала б ця команда, якби я був на AIX, Solaris або MINIX3 "приблизно ... в режимі очікування ... Мені важко отримати читання лічильника ... дисплей заморожений 0.00.
Калеб

2
У Gnu lsнемає --use-telepathyваріанту? Це найшвидший спосіб відображення лише потрібних файлів. Це може бути не портативним.
сумнівним

8
ls -l /folder | grep ^- | awk '{print $9}'

Що $9в цьому твердженні?
EmmyS

3
@EmmyS Це означає 9-е поле / стовпець виводу. Ця відповідь намагається проаналізувати lsвихід .
jw013

print $ NF` буде кращим, IMO. $ NF означає кількість полів, що було б 9, і це звичайне використання в AWK як хороша можливість навчити інших про $ NF.
Ілля Лінн

1
ls -l | grep -v ^d | grep name$

Що б зробило для цього рішення (яке вимагає декількох команд і труб) find?
HalosGhost

Це лаконічно, легко читати і дотримуватися конвенції ls. Мені легше запам'ятати, ніж знайти аргументи команди. Кожному своє і кудо за варіанти!
tkjef

0

Дозвольте мені сфотографуватися з використанням lsі труб:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

скажімо, останній стовпець - 9-й.


1
Що робити, якщо є файли з пробілами?
Йорданм

0

Якщо проблема переносимості -maxdepth викликає занепокоєння, ви можете використовувати:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

Я не експерт, але думаю, що це має працювати. Я гадаю, це виглядає трохи кумедно, але якщо ви говорите жахливо, це насправді не так. $ NF можна використовувати замість 9 $. Ви також можете зробити:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

що робить те саме (але, можливо, менш ефективно, ніж колишній ???).

Насправді, подумавши про інші пости, це виглядає так

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

це ще коротший і зрозуміліший спосіб.

Хтось, будь ласка, виправте мене, якщо я помиляюся. :-)


Парсинг, lsяк правило, не є хорошою ідеєю . Наприклад, у ваших хитрощів не вдасться назвати файли файлів з пробілом.
Мат

@mat - Дякую за виправлення. Прочитавши статтю, яку ви вказали (та jw013), я бачу, що ls не можна довіряти для виведення правильних імен файлів. Навіть якби я був переписати код AWK для друку все від $ 9 до кінця рядка (включаючи пробільні), цей Ls вихід все ще може бути помилковим. Це невтішно, і їх слід виправити ІМО. Знову дякую.
kkaszub


-1

Спробуйте цей псевдонім і скористайтеся ним:

alias l='ls -hLlF'

ls -hLlFпоказує підкаталоги, і він показує файли, починаючи з t_. То як це відповідає на питання?
Рафаель Аренс

Можливо, я неправильно зрозумів питання. ls -hLlF не відображатиме цільові каталоги пов'язаних каталогів.
Гранульований

Здається, так. Але ви не читали інших відповідей на питання?
Рафаель Аренс

-1

Простенька:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d


(1) Ця відповідь така проста, вона була дана раніше. (2) Чому ви вважаєте, що вам потрібно вказати повний шлях до каталогу?
Скотт

@Scott - це дуже швидкий і простий спосіб дійти до рішення. Повний шлях був визначений, щоб зробити відповідь універсальною ...
Digger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.