Перед 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
Предполагая, что ваши пути не содержат пробелов или новых строк:
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
С 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