У вас уже есть рабочий find | xargs ls
, который дает вам отсортированный список файлов, сперва новые объявления. (Как указывает @sjsam, предполагается, что ни один из ваших имен файлов не содержит символы новой строки.) Вы можете использовать функцию bash, чтобы поместить этот список в файл, по одной записи в строке, так что это может быть re ad by a while ... read
loop. Затем вы можете выйти из цикла, как только одна резервная копия завершится успешно.
# vvvvvvvvvvvvvvvvvvvvvv get the next filename into $tarname
while IFS= read -r tarname
do
tar -xf "$tarname" && break
# ^^^^^^^^ done with the loop if tar succeeds
done < <(find /config/config_*.tar -maxdepth 1 -type f -size +1k -print0 | xargs -0 ls -hat)
#^ ^^^^---- the process substitution
# |
# +--------- the redirection from the process subsitution
Обратите внимание, что вам нужно < <(...)
, а не только <(...)
.
(Кстати, вам нужно ls -hat
, или же ls -t
делать, а?)
Edit! ака Возьмите 3
Я был вдохновлен комментарий @ sjsam, чтобы написать ls0, замену ls
, который может предоставить NULL завершающим выход. Проверьте это и сообщите о проблеме, если найдете какие-либо ошибки! Он был протестирован с Perl 5.22 на Cygwin, но должен работать для большинства Perl 5s. Это единственный файл — для установки, введите ls0
на свой путь и chmod ugo+x ls0
.
Использование ls0
, метод выше может обрабатывать странно названные файлы с апломбом:
while IFS= read -r -d '' tarname
do
tar -xf "$tarname" && break
done < <(find /config/config_*.tar -maxdepth 1 -type f -size +1k -print0 | ls0 -t)
(как отмечено @sjsam, -d ''
функционально эквивалентна -d $'\0'
)
Take 2page sjsam links предлагает использовать perl
вместо ls
для сортировки имен файлов. Таким образом, вы можете обрабатывать имена файлов, в которых есть символы новой строки или другие странные символы.
Вот пример этой техники (не ответ на вопрос ОП). Я проверил его с именем файла, включая новую строку. Следующий код печатает файлы *.tar
в текущем каталоге, новее сначала. Этот пример печатает косую черту до и после каждого имени файла, чтобы вы могли видеть, что имена файлов с символами новой строки обрабатываются правильно. Протестировано на cygwin, bash 4.3.46, perl 5.22.2.
perl -e 'opendir(my $dirh, "."); print(join "\0", sort { -M $a <=> -M $b } grep /.tar$/, readdir($dirh))' \
| while IFS= read -r -d $'\0' name
do
printf "/%s/\n" "$name"
done
Итак, положив, что все вместе для кода, который (1) отвечает на вопрос OP и (2) является устойчивым к имени файла с странного содержания:
perl -e 'opendir(my $dirh, "."); print(join "\0", sort { -M $a <=> -M $b } grep /.tar$/, readdir($dirh))' \
| while read -r -d $'\0' tarname
do
tar -xf "$tarname" && break
done
или, используя замену процесса,
while IFS= read -r -d $'\0' tarname
do
tar -xf "$tarname" && break
done < <(perl -e 'opendir(my $dirh, "."); print(join "\0", sort { -M $a <=> -M $b } grep /.tar$/, readdir($dirh))')
Легко, правда? ;)
Источников:
- чтение каталоги в отсортированном порядке: this answer
- reference для теста
-M
данные нулевого завершающего
- чтения в Баше: this blog post (Баш-х
read
может используется с нулевыми символами)
- f iltering списка в Perl: this answer
[1] [http://mywiki.wooledge.org/ParsingLs#Why_you_shouldn.27t_parse_the_output_of_ls.281.29), чтобы проанализировать вывод ls. – sjsam
@sjsam Достаточно честный! Проверьте редактирование :). – cxw
Я использовал первую версию, так как в названии нет пробелов. – Alek