Рекурсивный скрипт bash для сбора информации о каждом файле в структуре каталогов

Как я могу рекурсивно работать через дерево каталогов и выполнять определенную команду для каждого файла и вывести путь в путь, имя файла, расширение, размер файла и некоторый другой конкретный текст в один файл в bash.

11
задан 23 January 2018 в 14:36

16 ответов

Я немного озадачен тем, почему никто еще не опубликовал его, но действительно bash имеет рекурсивные возможности, если вы включите опцию globstar и используете ** glob. Таким образом, вы можете написать (почти) чистый скрипт bash, который использует этот рекурсивный globstar следующим образом:

#!/usr/bin/env bash

shopt -s globstar

for i in ./**/*
do
    if [ -f "$i" ];
    then
        printf "Path: %s\n" "${i%/*}" # shortest suffix removal
        printf "Filename: %s\n" "${i##*/}" # longest prefix removal
        printf "Extension: %s\n"  "${i##*.}"
        printf "Filesize: %s\n" "$(du -b "$i" | awk '{print $1}')"
        # some other command can go here
        printf "\n\n"
    fi
done

Обратите внимание, что здесь мы используем расширение параметра, чтобы получить нужные нам части имени файла, re, не полагаясь на внешние команды, за исключением получения размера файла с помощью du и очистки вывода с помощью awk.

И когда он пересекает ваше дерево каталогов, ваш вывод должен выглядеть примерно так:

Path: ./glibc/glibc-2.23/benchtests
Filename: sprintf-source.c
Extension: c
Filesize: 326

Применяются стандартные правила использования скрипта: убедитесь, что он выполним с chmod +x ./myscript.sh и запустил его из текущего каталога через ./myscript.sh или поместил его в ~/bin и запустил source ~/.profile.

10
ответ дан 22 May 2018 в 17:10
  • 1
    Если вы печатаете полное имя файла, что добавляет расширение " дать вам? Возможно, вам действительно нужна информация MIME, что "$(file "$i")" (в приведенном выше скрипте как вторая часть printf) вернется? – pbhj 10 November 2017 в 01:42
  • 2
    @pbhj Мне лично? Ничего. Но ОП, который задал вопрос, спросил output the path, filename, extension, filesize , поэтому ответ соответствует тому, что задают. :) – Sergiy Kolodyazhnyy 10 November 2017 в 02:42

Я немного озадачен тем, почему никто еще не опубликовал его, но действительно bash имеет рекурсивные возможности, если вы включите опцию globstar и используете ** glob. Таким образом, вы можете написать (почти) чистый скрипт bash, который использует этот рекурсивный globstar следующим образом:

#!/usr/bin/env bash shopt -s globstar for i in ./**/* do if [ -f "$i" ]; then printf "Path: %s\n" "${i%/*}" # shortest suffix removal printf "Filename: %s\n" "${i##*/}" # longest prefix removal printf "Extension: %s\n" "${i##*.}" printf "Filesize: %s\n" "$(du -b "$i" | awk '{print $1}')" # some other command can go here printf "\n\n" fi done

Обратите внимание, что здесь мы используем расширение параметра, чтобы получить нужные нам части имени файла, re, не полагаясь на внешние команды, за исключением получения размера файла с помощью du и очистки вывода с помощью awk.

И когда он пересекает ваше дерево каталогов, ваш вывод должен выглядеть примерно так:

Path: ./glibc/glibc-2.23/benchtests Filename: sprintf-source.c Extension: c Filesize: 326

Применяются стандартные правила использования скрипта: убедитесь, что он выполним с chmod +x ./myscript.sh и запустил его из текущего каталога через ./myscript.sh или поместил его в ~/bin и запустил source ~/.profile.

11
ответ дан 18 July 2018 в 04:36

Я немного озадачен тем, почему никто еще не опубликовал его, но действительно bash имеет рекурсивные возможности, если вы включите опцию globstar и используете ** glob. Таким образом, вы можете написать (почти) чистый скрипт bash, который использует этот рекурсивный globstar следующим образом:

#!/usr/bin/env bash shopt -s globstar for i in ./**/* do if [ -f "$i" ]; then printf "Path: %s\n" "${i%/*}" # shortest suffix removal printf "Filename: %s\n" "${i##*/}" # longest prefix removal printf "Extension: %s\n" "${i##*.}" printf "Filesize: %s\n" "$(du -b "$i" | awk '{print $1}')" # some other command can go here printf "\n\n" fi done

Обратите внимание, что здесь мы используем расширение параметра, чтобы получить нужные нам части имени файла, re, не полагаясь на внешние команды, за исключением получения размера файла с помощью du и очистки вывода с помощью awk.

И когда он пересекает ваше дерево каталогов, ваш вывод должен выглядеть примерно так:

Path: ./glibc/glibc-2.23/benchtests Filename: sprintf-source.c Extension: c Filesize: 326

Применяются стандартные правила использования скрипта: убедитесь, что он выполним с chmod +x ./myscript.sh и запустил его из текущего каталога через ./myscript.sh или поместил его в ~/bin и запустил source ~/.profile.

11
ответ дан 24 July 2018 в 18:07

Хотя решения find просты и мощны, я решил создать более сложное решение, основанное на этой интересной функции, которую я видел несколько дней назад.

Здесь приведены дополнительные пояснения и два других сценария, основанных на текущем.

1. Создайте исполняемый файл сценария под названием walk, который находится в /usr/local/bin, чтобы быть доступным как команда оболочки:

sudo touch /usr/local/bin/walk
sudo chmod +x /usr/local/bin/walk
sudo nano /usr/local/bin/walk
Дополнительные пояснения и два других сценария, основанных на текущем, предоставляются здесь.

1. Содержание скрипта walk:

#!/bin/bash

# Colourise the output
RED='\033[0;31m'        # Red
GRE='\033[0;32m'        # Green
YEL='\033[1;33m'        # Yellow
NCL='\033[0m'           # No Color

file_specification() {
        FILE_NAME="$(basename "${entry}")"
        DIR="$(dirname "${entry}")"
        NAME="${FILE_NAME%.*}"
        EXT="${FILE_NAME##*.}"
        SIZE="$(du -sh "${entry}" | cut -f1)"

        printf "%*s${GRE}%s${NCL}\n"                    $((indent+4)) '' "${entry}"
        printf "%*s\tFile name:\t${YEL}%s${NCL}\n"      $((indent+4)) '' "$FILE_NAME"
        printf "%*s\tDirectory:\t${YEL}%s${NCL}\n"      $((indent+4)) '' "$DIR"
        printf "%*s\tName only:\t${YEL}%s${NCL}\n"      $((indent+4)) '' "$NAME"
        printf "%*s\tExtension:\t${YEL}%s${NCL}\n"      $((indent+4)) '' "$EXT"
        printf "%*s\tFile size:\t${YEL}%s${NCL}\n"      $((indent+4)) '' "$SIZE"
}

walk() {
        local indent="${2:-0}"
        printf "\n%*s${RED}%s${NCL}\n\n" "$indent" '' "$1"
        # If the entry is a file do some operations
        for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
        # If the entry is a directory call walk() == create recursion
        for entry in "$1"/*; do [[ -d "$entry" ]] && walk "$entry" $((indent+4)); done
}

# If the path is empty use the current, otherwise convert relative to absolute; Exec walk()
[[ -z "${1}" ]] && ABS_PATH="${PWD}" || cd "${1}" && ABS_PATH="${PWD}"
walk "${ABS_PATH}"      
echo                    

3. Объяснение:

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть. Внутри функции walk() я добавил этот цикл:
for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
Это означает, что для каждого $entry, который является файлом, будет выполняться функция file_specification(). Функция file_specification() состоит из двух частей. Первая часть получает данные, относящиеся к файлу - имя, путь, размер и т. Д. Вторая часть выводит данные в хорошо отформатированной форме. Для форматирования данных используется команда printf. И если вы хотите настроить скрипт, вы должны прочитать об этой команде - например, в этой статье. Функция file_specification() является хорошим местом, где вы можете поместить определенную команду, которая должна быть выполнена для каждого файла. Используйте этот формат: command "${entry}" Или вы можете сохранить вывод команды как переменную, а затем printf эту переменную и т. Д .: MY_VAR="$(command "${entry}")" printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$MY_VAR" Или непосредственно printf вывод команды: printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$(command "${entry}")" Раздел в попрошайничество, называемое Colourise the output, инициализирует несколько переменных, которые используются в команде printf для обработки результата. Подробнее об этом вы можете найти здесь. В нижней части скрипта добавлено дополнительное условие, касающееся абсолютных и относительных путей.

3. Примеры использования:

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть.

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть.

walk <directory name>
walk ./<directory name>
walk <directory name>/<sub directory>
В функции walk() я добавил этот цикл:
for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
Это означает, что для каждого $entry, который является файлом, будет выполнен function file_specification().

В функции walk() я добавил этот цикл:

walk > output.file
Функция file_specification() состоит из двух частей. Первая часть получает данные, относящиеся к файлу - имя, путь, размер и т. Д. Вторая часть выводит данные в хорошо отформатированной форме. Для форматирования данных используется команда printf. И если вы хотите настроить скрипт, вы должны прочитать об этой команде - например, эту статью.

Чтобы запустить walk для любого дочернего каталога:

Чтобы создать текстовый файл, основанный на выходе walk:

13
ответ дан 22 May 2018 в 17:10
  • 1
    Это много работы, но выглядит хорошо. Отличная работа ! – Sergiy Kolodyazhnyy 25 October 2017 в 12:45
  • 2
    Какой процесс вы используете для создания этих gifs @ pa4080? – pbhj 10 November 2017 в 01:43
  • 3
    @pbhj, под Ubuntu Я использую Peek , это просто и приятно, но иногда сбой и не имеет возможности редактирования. Большинство моих GIF-файлов создаются под Windows, где я записываю окно соединения VNC. У меня есть отдельная настольная машина, которую я использую для создания MS Office и GIF. Инструмент, который я использую, есть ScreenToGif . Это open source, бесплатный и имеет мощный редактор и механизм обработки. К сожалению, я не могу найти такой инструмент, как ScreenToGif для Ubuntu. – pa4080 10 November 2017 в 02:08

Вы можете использовать find для выполнения задания

find /path/ -type f -exec ls -alh {} \;

Это поможет вам, если вы просто хотите перечислить все файлы с размером.

-exec позволит вы должны выполнить пользовательскую команду или скрипт для каждого файла \;, используемого для одновременного анализа файлов, вы можете использовать +;, если хотите их конкатенировать (означает имена файлов).

10
ответ дан 22 May 2018 в 17:10
  • 1
    Это хорошо, но не отвечать на все упомянутые требования OP. – αғsнιη 25 October 2017 в 11:46
  • 2
    @ αғsнιη Я просто дал ему шаблон для работы. Я знаю, это не полный ответ на этот вопрос, так как я думаю, что сам вопрос имеет широкий охват. – Rajesh Rajendran 25 October 2017 в 11:52

Только с find.

find /path/ -type f -printf "path:%h  fileName:%f  size:%kKB Some Text\n" > to_single_file

Или вы можете использовать ниже:

find -type f -not -name "to_single_file"  -execdir sh -c '
    printf "%s %s %s %s Some Text\n" "$PWD" "${1#./}" "${1##*.}" $(stat -c %s "$1")
' _ {} \; > to_single_file
6
ответ дан 22 May 2018 в 17:10
  • 1
    Элегантный и простой (если вы знаете о find -printf). +1 – David Foerster 25 October 2017 в 16:18

Если вы знаете, насколько глубоким является дерево, самым простым способом будет использование подстановочного знака *.

Запишите все, что вы хотите сделать в качестве сценария оболочки или функции

function thing() { ... }

, затем запустите for i in *; do thing "$i"; done, for i in */*; do thing "$i"; done, ... и т. д.

В вашей функции / скрипте вы можете использовать несколько простых тестов для выделения файлов, с которыми хотите работать, и делай все, что с ними нужно.

1
ответ дан 22 May 2018 в 17:10
  • 1
    "это не будет работать, если в каком-либо из ваших имен файлов есть пробелы в них " ... потому что вы забыли процитировать свои переменные! Использовать " $ i " вместо $i. – muru 25 October 2017 в 12:38
  • 2
    @muru нет, причина, по которой он не работает, заключается в том, что «" петля разбивается на пробелы - " / 'расшифровывается в список всех файлов, разделенных пробелами. Вы можете обойти это, например. путем возиться с IFS, но в этот момент вы могли бы просто использовать find. – Benubird 25 October 2017 в 13:52
  • 3
    @ pa4080 не имеет отношения к этому ответу, но это выглядит супер полезным в любом случае, спасибо! – Benubird 25 October 2017 в 13:54
  • 4
    Я думаю, вы не понимаете, как работает for i in */*. Здесь протестируйте его: for i in */*; do printf "|%s|\n" "$i"; done – muru 25 October 2017 в 13:56
  • 5
    Вот доказательство важности кавычек: i.stack.imgur.com/oYSj2.png – pa4080 25 October 2017 в 14:06

find может сделать это:

find ./ -type f -printf 'Size:%s\nPath:%H\nName:%f\n'

Посмотрите на man find для других свойств файла.

Если вам действительно нужно расширение, вы можете добавить это :

find ./ -type f -printf 'Size:%s\nPath:%H\nName:%f\nExtension:' -exec sh -c 'echo "${0##*.}\n"' {} \;
1
ответ дан 22 May 2018 в 17:10

Если вы знаете, насколько глубоким является дерево, самым простым способом будет использование подстановочного знака *.

Запишите все, что вы хотите сделать в качестве сценария оболочки или функции

function thing() { ... }

, затем запустите for i in *; do thing "$i"; done, for i in */*; do thing "$i"; done, ... и т. д.

В вашей функции / скрипте вы можете использовать несколько простых тестов для выделения файлов, с которыми хотите работать, и делай все, что с ними нужно.

1
ответ дан 18 July 2018 в 04:36

find может сделать это:

find ./ -type f -printf 'Size:%s\nPath:%H\nName:%f\n'

Посмотрите на man find для других свойств файла.

Если вам действительно нужно расширение, вы можете добавить это :

find ./ -type f -printf 'Size:%s\nPath:%H\nName:%f\nExtension:' -exec sh -c 'echo "${0##*.}\n"' {} \;
1
ответ дан 18 July 2018 в 04:36

Хотя решения find просты и мощны, я решил создать более сложное решение, основанное на этой интересной функции, которую я видел несколько дней назад.

Здесь приведены дополнительные пояснения и два других сценария, основанных на текущем.

1. Создайте исполняемый файл сценария под названием walk, который находится в /usr/local/bin, чтобы быть доступным как команда оболочки:

sudo touch /usr/local/bin/walk sudo chmod +x /usr/local/bin/walk sudo nano /usr/local/bin/walk Дополнительные пояснения и два других сценария, основанных на текущем, предоставляются здесь.

1. Содержание скрипта walk:

#!/bin/bash # Colourise the output RED='\033[0;31m' # Red GRE='\033[0;32m' # Green YEL='\033[1;33m' # Yellow NCL='\033[0m' # No Color file_specification() { FILE_NAME="$(basename "${entry}")" DIR="$(dirname "${entry}")" NAME="${FILE_NAME%.*}" EXT="${FILE_NAME##*.}" SIZE="$(du -sh "${entry}" | cut -f1)" printf "%*s${GRE}%s${NCL}\n" $((indent+4)) '' "${entry}" printf "%*s\tFile name:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$FILE_NAME" printf "%*s\tDirectory:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$DIR" printf "%*s\tName only:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$NAME" printf "%*s\tExtension:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$EXT" printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$SIZE" } walk() { local indent="${2:-0}" printf "\n%*s${RED}%s${NCL}\n\n" "$indent" '' "$1" # If the entry is a file do some operations for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done # If the entry is a directory call walk() == create recursion for entry in "$1"/*; do [[ -d "$entry" ]] && walk "$entry" $((indent+4)); done } # If the path is empty use the current, otherwise convert relative to absolute; Exec walk() [[ -z "${1}" ]] && ABS_PATH="${PWD}" || cd "${1}" && ABS_PATH="${PWD}" walk "${ABS_PATH}" echo

3. Объяснение:

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть. Внутри функции walk() я добавил этот цикл: for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done Это означает, что для каждого $entry, который является файлом, будет выполняться функция file_specification(). Функция file_specification() состоит из двух частей. Первая часть получает данные, относящиеся к файлу - имя, путь, размер и т. Д. Вторая часть выводит данные в хорошо отформатированной форме. Для форматирования данных используется команда printf. И если вы хотите настроить скрипт, вы должны прочитать об этой команде - например, в этой статье. Функция file_specification() является хорошим местом, где вы можете поместить определенную команду, которая должна быть выполнена для каждого файла. Используйте этот формат: command "${entry}" Или вы можете сохранить вывод команды как переменную, а затем printf эту переменную и т. Д .: MY_VAR="$(command "${entry}")" printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$MY_VAR" Или непосредственно printf вывод команды: printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$(command "${entry}")" Раздел в попрошайничество, называемое Colourise the output, инициализирует несколько переменных, которые используются в команде printf для обработки результата. Подробнее об этом вы можете найти здесь. В нижней части скрипта добавлено дополнительное условие, касающееся абсолютных и относительных путей.

3. Примеры использования:

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть.

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть.

walk <directory name> walk ./<directory name> walk <directory name>/<sub directory> В функции walk() я добавил этот цикл: for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done Это означает, что для каждого $entry, который является файлом, будет выполнен function file_specification().

В функции walk() я добавил этот цикл:

walk > output.file Функция file_specification() состоит из двух частей. Первая часть получает данные, относящиеся к файлу - имя, путь, размер и т. Д. Вторая часть выводит данные в хорошо отформатированной форме. Для форматирования данных используется команда printf. И если вы хотите настроить скрипт, вы должны прочитать об этой команде - например, эту статью.

Чтобы запустить walk для любого дочернего каталога:

Чтобы создать текстовый файл, основанный на выходе walk:

13
ответ дан 18 July 2018 в 04:36

Только с find.

find /path/ -type f -printf "path:%h fileName:%f size:%kKB Some Text\n" > to_single_file

Или вы можете использовать ниже:

find -type f -not -name "to_single_file" -execdir sh -c ' printf "%s %s %s %s Some Text\n" "$PWD" "${1#./}" "${1##*.}" $(stat -c %s "$1") ' _ {} \; > to_single_file
6
ответ дан 18 July 2018 в 04:36

Если вы знаете, насколько глубоким является дерево, самым простым способом будет использование подстановочного знака *.

Запишите все, что вы хотите сделать в качестве сценария оболочки или функции

function thing() { ... }

, затем запустите for i in *; do thing "$i"; done, for i in */*; do thing "$i"; done, ... и т. д.

В вашей функции / скрипте вы можете использовать несколько простых тестов для выделения файлов, с которыми хотите работать, и делай все, что с ними нужно.

1
ответ дан 24 July 2018 в 18:07
  • 1
    "это не будет работать, если в каком-либо из ваших имен файлов есть пробелы в них & quot; ... потому что вы забыли процитировать свои переменные! Использовать & quot; $ i & quot; вместо $i. – muru 25 October 2017 в 12:38
  • 2
    @muru нет, причина, по которой он не работает, заключается в том, что «& quot; петля разбивается на пробелы - & quot; / 'расшифровывается в список всех файлов, разделенных пробелами. Вы можете обойти это, например. путем возиться с IFS, но в этот момент вы могли бы просто использовать find. – Benubird 25 October 2017 в 13:52
  • 3
    @pa4080 не относится к этому ответу, но все равно выглядит супер полезно, спасибо! – Benubird 25 October 2017 в 13:54
  • 4
    Я думаю, вы не понимаете, как работает for i in */*. Здесь протестируйте его: for i in */*; do printf "|%s|\n" "$i"; done – muru 25 October 2017 в 13:56
  • 5
    Вот доказательство важности кавычек: i.stack.imgur.com/oYSj2.png – pa4080 25 October 2017 в 14:06

find может сделать это:

find ./ -type f -printf 'Size:%s\nPath:%H\nName:%f\n'

Посмотрите на man find для других свойств файла.

Если вам действительно нужно расширение, вы можете добавить это :

find ./ -type f -printf 'Size:%s\nPath:%H\nName:%f\nExtension:' -exec sh -c 'echo "${0##*.}\n"' {} \;
1
ответ дан 24 July 2018 в 18:07

Хотя решения find просты и мощны, я решил создать более сложное решение, основанное на этой интересной функции, которую я видел несколько дней назад.

Здесь приведены дополнительные пояснения и два других сценария, основанных на текущем.

1. Создайте исполняемый файл сценария под названием walk, который находится в /usr/local/bin, чтобы быть доступным как команда оболочки:

sudo touch /usr/local/bin/walk sudo chmod +x /usr/local/bin/walk sudo nano /usr/local/bin/walk Дополнительные пояснения и два других сценария, основанных на текущем, предоставляются здесь.

1. Содержание скрипта walk:

#!/bin/bash # Colourise the output RED='\033[0;31m' # Red GRE='\033[0;32m' # Green YEL='\033[1;33m' # Yellow NCL='\033[0m' # No Color file_specification() { FILE_NAME="$(basename "${entry}")" DIR="$(dirname "${entry}")" NAME="${FILE_NAME%.*}" EXT="${FILE_NAME##*.}" SIZE="$(du -sh "${entry}" | cut -f1)" printf "%*s${GRE}%s${NCL}\n" $((indent+4)) '' "${entry}" printf "%*s\tFile name:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$FILE_NAME" printf "%*s\tDirectory:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$DIR" printf "%*s\tName only:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$NAME" printf "%*s\tExtension:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$EXT" printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$SIZE" } walk() { local indent="${2:-0}" printf "\n%*s${RED}%s${NCL}\n\n" "$indent" '' "$1" # If the entry is a file do some operations for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done # If the entry is a directory call walk() == create recursion for entry in "$1"/*; do [[ -d "$entry" ]] && walk "$entry" $((indent+4)); done } # If the path is empty use the current, otherwise convert relative to absolute; Exec walk() [[ -z "${1}" ]] && ABS_PATH="${PWD}" || cd "${1}" && ABS_PATH="${PWD}" walk "${ABS_PATH}" echo

3. Объяснение:

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть. Внутри функции walk() я добавил этот цикл: for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done Это означает, что для каждого $entry, который является файлом, будет выполняться функция file_specification(). Функция file_specification() состоит из двух частей. Первая часть получает данные, относящиеся к файлу - имя, путь, размер и т. Д. Вторая часть выводит данные в хорошо отформатированной форме. Для форматирования данных используется команда printf. И если вы хотите настроить скрипт, вы должны прочитать об этой команде - например, в этой статье. Функция file_specification() является хорошим местом, где вы можете поместить определенную команду, которая должна быть выполнена для каждого файла. Используйте этот формат: command "${entry}" Или вы можете сохранить вывод команды как переменную, а затем printf эту переменную и т. Д .: MY_VAR="$(command "${entry}")" printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$MY_VAR" Или непосредственно printf вывод команды: printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$(command "${entry}")" Раздел в попрошайничество, называемое Colourise the output, инициализирует несколько переменных, которые используются в команде printf для обработки результата. Подробнее об этом вы можете найти здесь. В нижней части скрипта добавлено дополнительное условие, касающееся абсолютных и относительных путей.

3. Примеры использования:

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть.

Основной механизм функции walk() довольно хорошо описан Zanna в ее ответе. Поэтому я опишу только новую часть.

walk <directory name> walk ./<directory name> walk <directory name>/<sub directory> В функции walk() я добавил этот цикл: for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done Это означает, что для каждого $entry, который является файлом, будет выполнен function file_specification().

В функции walk() я добавил этот цикл:

walk > output.file Функция file_specification() состоит из двух частей. Первая часть получает данные, относящиеся к файлу - имя, путь, размер и т. Д. Вторая часть выводит данные в хорошо отформатированной форме. Для форматирования данных используется команда printf. И если вы хотите настроить скрипт, вы должны прочитать об этой команде - например, эту статью.

Чтобы запустить walk для любого дочернего каталога:

Чтобы создать текстовый файл, основанный на выходе walk:

13
ответ дан 24 July 2018 в 18:07
  • 1
    Это много работы, но выглядит хорошо. Отличная работа ! – Sergiy Kolodyazhnyy 25 October 2017 в 12:45
  • 2
    Какой процесс вы используете для создания этих gifs @ pa4080? – pbhj 10 November 2017 в 01:43
  • 3
    @pbhj, под Ubuntu Я использую Peek , это просто и приятно, но иногда сбой и не имеет возможности редактирования. Большинство моих GIF-файлов создаются под Windows, где я записываю окно соединения VNC. У меня есть отдельная настольная машина, которую я использую для создания MS Office и GIF. Инструмент, который я использую, есть ScreenToGif . Это open source, бесплатный и имеет мощный редактор и механизм обработки. К сожалению, я не могу найти такой инструмент, как ScreenToGif для Ubuntu. – pa4080 10 November 2017 в 02:08

Только с find.

find /path/ -type f -printf "path:%h fileName:%f size:%kKB Some Text\n" > to_single_file

Или вы можете использовать ниже:

find -type f -not -name "to_single_file" -execdir sh -c ' printf "%s %s %s %s Some Text\n" "$PWD" "${1#./}" "${1##*.}" $(stat -c %s "$1") ' _ {} \; > to_single_file
6
ответ дан 24 July 2018 в 18:07
  • 1
    Это хорошо, но не отвечать на все упомянутые требования OP. – αғsнιη 25 October 2017 в 11:46
  • 2
    @ αғsнιη Я просто дал ему шаблон для работы. Я знаю, это не полный ответ на этот вопрос, так как я думаю, что сам вопрос имеет широкий охват. – Rajesh Rajendran 25 October 2017 в 11:52
  • 3
    Элегантный и простой (если вы знаете о find -printf). +1 – David Foerster 25 October 2017 в 16:18

Другие вопросы по тегам:

Похожие вопросы: