Як показати лише приховані файли в Терміналі?


154

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

Команда ls -aперераховує всі файли, включаючи приховані, але мені потрібно лише перелічити приховані файли.

Яку команду я повинен використовувати?


1
Простий ls -ld .*або ls -ald .*спрацює
Джон Строд

Відповіді:


189

Команда:

ls -ld .?* 

Буде лише список прихованих файлів.

Поясніть:

 -l     use a long listing format

 -d, --directory
              list  directory entries instead of contents, and do not derefer‐
              ence symbolic links

.?* will only state hidden files 

8
Вам не потрібні два знаки запитання, * прикриває його (? Відповідає лише одному символу, * відповідає будь-якій кількості).
psusi

13
@psusi, я думаю, що наміром є виключення .та ..зі збігу. Однак це також виключає (цілком законні) односимвольні приховані імена файлів , таких як .a, .1і так далі. Можливо, краще розширений глобус буде .!(|.)тобто буквальною крапкою, за якою слідує все, крім нічого або іншої (однієї) крапки, тобтоls -d .!(|.)
steeldriver

@steeldriver, акуратний, то ?? версія не виключає "". і "..". Це здається результатом цікавої примхи: ні? ні * не буде відповідати крапці, але? повинно відповідати чомусь інакше ім'я ігнорується.
psusi

Для ідентифікації каталогів та файлів додайте опцію F, тобто, імена директорій ls -ldF.? * Мають "/", оскільки останні файли символів не мають.
RCF

1
Це майже працює, за винятком того, що він містить список прихованих папок типу .vim, які я вважаю тут не файлом. Я його трохи модифікую як ls -ldp.? * | grep -v / Це лише список прихованих файлів, не прихованих папок
Фред Ян

31
ls -d .!(|.)

Робить саме те, що шукає ОП.


1
Як це працює?
SarcasticSully

список каталогу що-небудь з. і нічого не перераховувати без одного - це те, що воно в значній мірі перекладається.
Патрік

1
Я розумію, що в !(pattern-list), pattern-listце список одного або декількох шаблонів, розділених символом a |, але для мене це заплутано те, що у вас немає шаблону зліва від |. Не могли б ви пояснити мені цей синтаксис?
Карлос Мендоса

2
@CarlosMendoza, який став би порожнім шаблоном, тому це як би .не супроводжується (нічого або .), виключаючи .себе і ...
муру

16

Якщо ви просто хочете, щоб файли у вашому поточному каталозі (без рекурсії), ви можете це зробити

echo .[^.]*

Це дозволить надрукувати імена всіх файлів, ім’я яких починається з а, .а потім - один або кілька неточних символів. Зауважте, що це не вдасться для файлів, ім'я яких починається з послідовних крапок, тому, наприклад ....foo, не відображатиметься.

Ви також можете використовувати find:

find -mindepth 1 -prune -name '.*'

У -mindepthгарантую , що ми не відповідаємо .і -pruneзасобів , які findзійдуть в підкаталоги.



4

Використання findта awk,

find . -type f | awk -F"/" '$NF ~ /^\..*$/ {print $NF}'

Пояснення:

find . -type f -> Список усіх файлів у поточному каталозі, а також шлях,

./foo.html
./bar.html
./.foo1

awk -F"/" '$NF ~ /^\..*$/ {print $NF}'

/як сепаратор поля awk перевіряє, чи останнє поле дивиться крапкою чи ні. Якщо він починається з крапки, то він друкує останнє поле відповідного рядка.


Ви могли просто використовувати find -type f. Вам не потрібно явно вказати шлях пошуку або -name "*".
тердон

3

find зазвичай є кращим варіантом для складних пошуків, ніж використання глобальних імен.

find . -mindepth 1 -maxdepth 1 -name '.*'

або

find . -mindepth 1 -maxdepth 1 -name '.*' -o -name '*~'

find . шукає поточний каталог

-mindepth 1виключає. і .. зі списку

-maxdepth 1 обмежує пошук у поточному каталозі

-name '.*' знайти імена файлів, які починаються з крапки

-o або

-name '*~' знайти імена файлів, які закінчуються тильдом (зазвичай це резервні файли з програм редагування тексту)

Однак ця та всі інші відповіді пропускають файли, які знаходяться у .hiddenфайлі поточного каталогу . Якщо ви пишете сценарій, ці рядки будуть читати .hiddenфайл та відображати назви файлів із тих, що існують.

if [[ -f .hidden]] # if '.hidden' exists and is a file
then
    while read filename # read file name from line
    do
        if [[ -e "$filename" ]] # if the read file name exists
        then
            echo "$filename" # print it
        fi
    done < .hidden # read from .hidden file
fi

Який .hiddenфайл? Чому б коли-небудь існував файл, який називається, .hiddenякий містить імена файлів? У будь-якому випадку, якщо є один, чому б ти зробив щось таке складне, коли все, що тобі було б потрібно cat .hidden? Ваша findкоманда правильна (ish), але -name '*~'це не має значення. Файли, які закінчуються в тильдах, є резервними файлами, але не прихованими.
тердон

@terdon .hiddenФайл призначений для файлів і папок, які ви хочете приховати, коли ви не можете змінити ім'я файла / папки, щоб почати з крапки. Що стосується файлів, які закінчуються в тильдах, це залежить від системи. ls -Bігнорує такі файли, як і більшість дослідників файлів GUI.
Марк Н

cat .hiddenможуть відображатися файли, які більше не існують, якщо ці файли були видалені або переміщені з моменту додавання до .hiddenфайлу.
Марк Н

Це добре працює.
Penghe Geng

2

Я думаю, що ви можете це зробити за допомогою наступної команди.

ls -a | grep "^\." | grep -v "^\.$" | grep -v "^\..$"

ls -a команда, яку ви ввели, що показує всі файли та каталоги в поточному робочому каталозі.

grep "^\."Команда, яку я додав, фільтрує вихід, показуючи лише приховані файли (це ім'я починається з ".").

grep -v "^\.$" | grep -v "^\..$" Команда, яку я додав, фільтрує вихід, щоб виключити., .. (Вони є поточним та батьківським каталогом).

Якщо деякі назви файлів можуть мати більше рядка з "\n", приклад вище може бути невірним.

Тому я пропоную наступну команду для вирішення цього питання.

find -maxdepth 1 -name ".[!.]*"


@ RaduRădeanu Я бачив ваш коментар, Це так добре. Я знову відредагував свою відповідь. Дякую за Ваш коментар
xiaodongjie

2

Що ще ви могли зробити, is ls .?*або ls .!(|)це покаже вам все в поточному режимі прихованих файлів / dirs вгорі та інших файлів / dirs внизу

наприклад: з мого терміналу

$ ls .?*       
.bash_history    .dmrc        .macromedia   .weather
.bash_logout     .gksu.lock   .profile      .wgetrc
.bash_profile    .bashrc.save .ICEauthority .toprc           .Xauthority
.bashrc          .lastdir     .viminfo      .xsession-errors
.bashrc~         .dircolors   .lynxrc       .vimrc           .xsession-errors.old

..:
Baron

.adobe:
Flash_Player

.aptitude:
cache  config

.cache:
compizconfig-1                              rhythmbox
dconf                                       shotwell

Тепер зауважте у наведених вище результатах, він показує вам кожен файл / dir зі своїм субдірром та будь-які приховані файли прямо внизу.

[1:0:248][ebaron@37signals:pts/4][~/Desktop]
$ ls .!(|)
.bash_aliases  .bashrc1  .bashrc1~

..:
askapache-bash-profile.txt  examples.desktop             Public           top-1m.csv
backups             Firefox_wallpaper.png        PycharmProjects          top-1m.csv.zip
Desktop             java_error_in_PYCHARM_17581.log  Shotwell Import Log.txt  topsites.txt
Documents           Music                Templates            Videos
Downloads           Pictures                 texput.log           vmware

Вибачте, я не можу коментувати. щоб пояснити різницю між тут ls .?*і @ cioby23 відповідь ls -d .[!.]* .??*А чому це насправді друкувати приховані файли в два рази , тому що буквально ви питаєте двічі .??*, .?*, .[!.]*вони те ж саме, так що додавання будь-якого з них з різними символами команди будуть друкувати в два рази.


1

Ви також можете використовувати:

ls -d .[!.]* .??*

Це дозволить вам відображати звичайні приховані та приховані файли, які починаються, наприклад, з 2 або 3 крапок: ..hidden_file


1
Цим я отримую всі приховані файли двічі.
TuKsn

1

ви можете використовувати команду

ls -Ad .??*

Це має перевагу в тому, що дозволяє перелічити багато стовпців, на відміну від підходу, що базується на ls -a | grep "^\."грепі


1

Усі відповіді поки що засновані на тому, що файли (або каталоги), імена яких починаються з крапки, "приховані". Я придумав інше рішення, яке може бути не настільки ефективним, але це рішення не передбачає нічого про назви прихованих файлів, а тому уникає внесення списку ..в результат (як і відповідь, що приймається на даний момент).

Повна команда:

ls -d $(echo -e "$(\ls)\n$(\ls -A)" | sort | uniq -u)

Пояснення

Для цього потрібно перерахувати всі файли (та каталоги) двічі,

echo -e "$(\ls)\n$(\ls -A)"

але показувати приховані файли лише один раз -A.

Далі список сортується, | sortзавдяки чому звичайні (невідомі) файли з’являються двічі та поруч.

Потім видаліть усі рядки, які з’являються не один раз | uniq -u, залишивши лише унікальні рядки.

Нарешті, використовуйте lsще раз, щоб перелічити всі файли зі спеціальними параметрами користувача та без перерахування вмісту каталогів у списку -d.

EDIT (обмеження):

Як зауважив Муру, це рішення не працюватиме належним чином, якщо є файли з такими іменами, як, escaped\ncharacter.txtтому що echo -eрозділить ім'я файлу на два рядки. Він також не буде працювати, як очікувалося, якщо є два приховані файли з майже однаковим іменем, за винятком спеціального символу, таких як .foo[tab].txtі .foo[new-line].txtяк обидва вони надруковані як .foo?.txtі будуть усуненіuniq -u


1
Я думаю, що це майже визначення прихованих файлів. Навіть походження цих прихованих файлів походить від помилки в роботі з .першим символом.
муру

Я згадую це (як факт) у першому пункті. Однак це все-таки отримує інший результат, ніж прийнята нині відповідь
алехандро

Звичайно, це виключає .., але мені цікаво, наскільки добре він працює з іменами, що містять спеціальні символи.
муру

Я не знаю точно, що ви маєте на увазі під спеціальними символами, але я думаю, що це не складе проблем, оскільки це рішення не передбачає нічого про назви файлів
alejandro

Насправді ви припускаєте хоча б одне: у назви файлів немає нових рядків. Крім того: у іменах файлів немає послідовностей втечі, які echo -eбудуть інтерпретувати. Також: lsне заблокуйте назви файлів, щоб дві різні імена файлів відображалися однаково (наприклад, у деяких версіях lsвикористовуватимуться ?для спеціальних символів, тому .foo\tbar( \t=> вкладка) та .foo\nbar( \n=> новий рядок) обидва відображатимуться як foo?bar).
муру

1

Крім того, ви також можете використовувати echo .*

напр

user@linux:~$ echo .*
. .. .bash_aliases .bash_history .bash_logout .bashrc
user@linux:~$

Якщо ви віддаєте перевагу у форматі довгого списку, просто перетворіть пробіл у новий рядок.

user@linux:~$ echo .* | tr ' ' '\n'
.
..
.bash_aliases
.bash_history
.bash_logout
.bashrc
user@linux:~$ 

0

З bash, встановлення GLOBIGNOREспеціальної змінної є деяким не порожнім значенням, щоб її ігнорувати .і ..при розширенні глобусів. З документів Bash :

GLOBIGNOREЗмінної оболонки можуть бути використані для обмеження безлічі імен файлів , відповідних шаблоном. Якщо GLOBIGNOREвстановлено, кожне ім'я відповідного файла, яке також відповідає одному з шаблонів у GLOBIGNORE, видаляється зі списку збігів. Якщо nocaseglobпараметр встановлений, відповідність шаблонам у GLOBIGNOREвиконується незалежно від випадку. Імена файлів .і ..завжди ігноруються, коли GLOBIGNOREвстановлено, а не є недійсним. Однак встановлення GLOBIGNOREненульового значення може призвести до ввімкнення параметра оболонки dotglob, тому всі інші імена файлів, що починаються з ‘.', будуть відповідати.

Якщо ми встановимо це на .:..обидва, .і ..будемо проігноровано. Оскільки встановлення його на що-небудь ненулеве також отримає таку поведінку, ми можемо також встановити його як раз.

Тому:

GLOBIGNORE=.
ls -d .*
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.