Рекурсивный список файлов в CLI Linux с указанием пути относительно текущего каталога

224

Это похоже на этот вопрос , но я хочу включить путь относительно текущего каталога в Unix. Если я сделаю следующее:

ls -LR | grep .txt

Это не включает полные пути. Например, у меня есть следующая структура каталогов:

test1/file.txt
test2/file1.txt
test2/file2.txt

Код выше вернет:

file.txt
file1.txt
file2.txt

Как я могу заставить его включать пути относительно текущего каталога, используя стандартные команды Unix?

Дэррил Хейн
источник
4
Это просто показывает, что в ls отсутствует эта функция.
Арджун Сингри
1
Обидно, что все эти решения требуют findили tree. Я ssh'ing в устройство Android, где у меня, кажется, только есть ls, и ни один из этих других инструментов: /
Ponkadoodle

Ответы:

304

Используйте find:

find . -name \*.txt -print

В системах, использующих GNU find, как и в большинстве дистрибутивов GNU / Linux, вы можете не указывать -print.

Андру Лувизи
источник
11
... и в этом отношении вы можете опустить "."
Адам Митц
7
Для абсолютных путей используйтеfind $(pwd) -name \*.txt
Zags
2
Если шаблон имеет часть имени каталога, следует использовать -path "*docs/*.txt"вместо -name. -wholenameтакой же как-path
дашесы
9
Используется -type fтолько для возврата файлов, а не каталогов, символических ссылок и т. Д.
пользователь
2
-name "*.txt"НЕ будет соответствовать file.TXT- всегда используйте -iname "*.txt"вместо этого, который не зависит от регистра.
ccpizza
73

Используйте treeс -f(полный путь) и -i(без отступов):

tree -if --noreport .
tree -if --noreport directory/

Затем вы можете использовать, grepчтобы отфильтровать те, которые вы хотите.


Если команда не найдена, вы можете установить ее:

Введите следующую команду для установки команды дерева в RHEL / CentOS и Fedora linux:

# yum install tree -y

Если вы используете Debian / Ubuntu, введите в свой терминал Mint Linux следующую команду:

$ sudo apt-get install tree -y
Стивен Айронс
источник
2
какой-либо параметр, чтобы перечислить только файлы и исключить папки?
thebugfinder
25

Попробуй find. Вы можете посмотреть это точно на странице руководства, но это как-то так:

find [start directory] -name [what to find]

так что для вашего примера

find . -name "*.txt"

должен дать вам то, что вы хотите.

Джонатан Адельсон
источник
9

Вы можете использовать вместо поиска:

find . -name '*.txt'
Шерм Пендли
источник
5

Это делает трюк:

ls -R1 $PWD | while read l; do case $l in *:) d=${l%:};; "") d=;; *) echo "$d/$l";; esac; done | grep -i ".txt"

Но он делает это, «грешив» с помощью анализа ls, что считается сообществом GNU и Ghostscript дурным тоном.

Эль Гесто
источник
2
@CAFEBABE: считается, что анализ результатов является табу, lsпотому что это обычно приводит к ошибкам. Данное предложение пыталось это высказать. У этого также была шутка в этом, который я удалил.
Адам Кац
4
DIR=your_path
find $DIR | sed 's:""$DIR""::'

'sed' удалит 'your_path' из всех результатов 'find'. И вы получаете по пути «DIR».

ч-дим
источник
это именно то, что мне нужно, но он все равно показывает мне полный путь?
v3nt
1
не используйте апостроф - find / tmp | sed s: "/ tmp" :: | больше
Kieren Dixon
4

Чтобы получить действительные полные имена файлов нужных файлов с помощью команды find, используйте ее с командой pwd:

find $(pwd) -name \*.txt -print
ZaSter
источник
1

Вот скрипт Perl:

sub format_lines($)
{
    my $refonlines = shift;
    my @lines = @{$refonlines};
    my $tmppath = "-";

    foreach (@lines)
    {
        next if ($_ =~ /^\s+/);
        if ($_ =~ /(^\w+(\/\w*)*):/)
        {
            $tmppath = $1 if defined $1;    
            next;
        }
        print "$tmppath/$_";
    }
}

sub main()
{
        my @lines = ();

    while (<>) 
    {
        push (@lines, $_);
    }
    format_lines(\@lines);
}

main();

использование:

ls -LR | perl format_ls-LR.pl
Эрик Келлер
источник
Это ужасная программа на Perl. Это, вероятно, в 2-3 раза длиннее и сложнее, чем нужно.
Брэд Гилберт
1

Вы можете создать функцию оболочки, например, в вашем .zshrcили .bashrc:

filepath() {
    echo $PWD/$1
}

filepath2() {
    for i in $@; do
        echo $PWD/$i
    done
}

Первый будет работать только на отдельные файлы, очевидно.

rxw
источник
1

Найдите файл с именем «filename» в вашей файловой системе, начав поиск с корневого каталога «/». «Имя файла»

find / -name "filename" 
user2101432
источник
1

Если вы хотите сохранить подробности, включите в вывод ls, например, размер файла и т. Д., Это должно сработать.

sed "s|<OLDPATH>|<NEWPATH>|g" input_file > output_file
rajeshk
источник
1

В оболочке fish вы можете сделать это для рекурсивного перечисления всех PDF-файлов, в том числе в текущем каталоге:

$ ls **pdf

Просто удалите «pdf», если вы хотите файлы любого типа.

rien333
источник
0

Вы можете реализовать эту функцию следующим образом.
Во-первых, с помощью команды ls, указывающей на целевой каталог. Позже с помощью команды find отфильтруйте результат. С вашего случая это звучит так - всегда имя файла начинается со слова file***.txt

ls /some/path/here | find . -name 'file*.txt'   (* represents some wild card search)
Сириш Ярлагадда
источник
0

В mycase, с командой дерева

Относительный путь

tree -ifF ./dir | grep -v '^./dir$' | grep -v '.*/$' | grep '\./.*' | while read file; do
  echo $file
done

Абсолютный путь

tree -ifF ./dir | grep -v '^./dir$' | grep -v '.*/$' | grep '\./.*' | while read file; do
  echo $file | sed -e "s|^.|$PWD|g"
done
Мацумото Казуя
источник