рекурсивный поиск и печать самого последнего файла tar.gz в каждом каталоге

Перед cat выполните echo или printf имени файла:

while read line; do printf '%s\n' "$line"; cat "$line"; done <locationfile.txt >finalfile

Или, более читабельно:

while read line; do
  printf '%s\n' "$line"
  cat "$line"
done <locationfile.txt >finalfile

Обратите внимание, что для этого требуются все пути в locationfile.txt , чтобы в них не было \ .

Хотя наличие \ в именах путей очень необычно, было бы безопаснее использовать

while read -r line; do
  printf '%s\n' "$line"
  cat "$line"
done <locationfile.txt >finalfile

... у которого нет таких же ограничений.

Добавление проверки, чтобы убедиться, что файл действительно существует, и вывод предупреждения, если это не так:

while read -r line; do
  if [[ -f "$line" ]]; then
    printf '%s\n' "$line"
    cat "$line"
  else
    printf 'Warning: "%s" does not exist\n' "$line" >&2
  fi
done <locationfile.txt >finalfile

«Не существует» здесь означает «по крайней мере, не является обычным файлом».

Если вы хотите, чтобы там же был "" как своего рода маркер содержимого-конца файла, просто поместите его после cat :

while read -r line; do
  if [[ -f "$line" ]]; then
    printf '%s\n' "$line"
    cat "$line"
    echo '""'
  else
    printf 'Warning: "%s" does not exist\n' "$line" >&2
  fi
done <locationfile.txt >finalfile

И наконец, дайте вещам самодокументированные имена:

while read -r file_path; do
  if [[ -f "$file_path" ]]; then
    printf '%s\n' "$file_path"
    cat "$file_path"
    echo '""'
  else
    printf 'Warning: "%s" does not exist\n' "$file_path" >&2
  fi
done <file_paths.txt >files_concat_with_paths.txt
1
29.04.2017, 01:16
2 ответа

Предполагая, что ваши пути не содержат пробелов или новых строк:

find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1

найдет все tar-архивы, запустит данный фрагмент оболочки в каждом содержащем каталоге и отфильтрует результат, чтобы только один результат хранится для каждого каталога.

Чтобы просмотреть содержимое архивов, предполагая, что их имена файлов также не содержат пробелов или новых строк:

find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1 | tr ' ' / | xargs -n 1 tar tvf

заменит пробел, отделяющий путь от имени файла, на «/» и передаст результат в xargs , который будет запускать tar tvf для каждого файла.

Для запроса между каждым тарболом добавьте -p к команде xargs:

find . -name \*.tar.\* -execdir sh -c "echo -n \"\${PWD} \"; ls -t *.tar.* | head -n 1" \; | sort -u -k1,1 | tr ' ' / | xargs -p -n 1 tar tvf
2
27.01.2020, 23:19

С zsh, в обычном режиме только для записи:

for dir (*/*(N/)) (){(($#)) && tar tvf $1} $dir/*.tar.gz(Nom[1])
  • для var (значения) cmd: более короткая форма для переменных значений; выполнить команду; done
  • (N/), (Nom[1]): квалификаторы glob
    • N: расширяется до нуля, если совпадений нет (nullglob)
    • /: только каталоги
    • om: порядок по времени модификации (самые новые сначала)
    • [1] : первое совпадение only
  • (){...} args: анонимные функции со своими аргументами.

С инструментами GNU (по-прежнему не делающими предположений о том, какие байты могут содержать имена файлов, но обходя скрытые каталоги и включая скрытые файлы tar.gz) и любой оболочкой, подобной Борну, эквивалентом может быть:

LC_ALL=C find . -mindepth 3 -maxdepth 3 -name '*.tar.gz' -printf '%T@:%p\0' |
  sort -zn | LC_ALL=C awk -v RS='\0' -v ORS='\0' '
    {match($0, ":((.*)/.*)", parts); newest[parts[2]] = parts[1]}
    END {for (dir in newest) print newest[dir]}' |
    xargs -r0n1 tar tvf        
2
27.01.2020, 23:19

Теги

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