Вот один лайнер с использованием sed
и awk
:
sed '/^$/d' filename | awk '!a[$1]++'
Комбинация grep
и awk
:
grep . filename | awk '!a[$1]++'
As @ cas предложил, вы также можете сделать это с помощью одной команды awk
.
awk '!x[$1]++ && ! /^[[:blank:]]*$/' filename
Мне нравятся простые для
циклов ...
for file in basedir/*/*.gz
do
gzip -cd < "$file" | xz > "${file%%.gz}.xz"
done
... по крайней мере, если ваша структура каталогов регулярная и достаточно простая. Если вам нужно пройти на неизвестные глубины или выполнить дополнительные условия при выборе файла, вам все равно придется придерживаться find
или аналогичного.
find . -name '*.gz' -type f -exec bash -o pipefail -Cc '
for file do
gunzip < "$file" | xz > "${file%.gz}.xz" && rm -f "$file"
done' bash {} +
-C
предотвращает перезапись существующего файла и не будет следовать символическим ссылкам , кроме , если исходящий файл является нестандартным файлом или ссылкой на нестандартный файл, поэтому вы не потеряете данные, если у вас нет, например, file.gz
и file.xz
, которые являются символической ссылкой на / dev / null
. Чтобы защититься от этого, вы можете использовать вместо него zsh
, а также использовать функцию -execdir
некоторых реализаций find
для хорошей меры и предотвращения некоторых состояний гонки:
find . -name '*.gz' -type f -execdir zsh -o pipefail -c '
zmodload zsh/system || exit
for file do
gunzip < "$file" | (
sysopen -u 1 -w -o excl -- "${file%.gz}.xz" && xz) &&
rm -f -- "$file"
done' zsh {} +
Или для очистки xz
файлов после неудачных повторных сжатий:
find . -name '*.gz' -type f -execdir zsh -o pipefail -c '
zmodload zsh/system || exit
for file do
sysopen -u 1 -w -o excl -- "${file%.gz}.xz" &&
if gunzip < "$file" | xz; then
rm -f -- "$file"
else
rm -f -- "${file%.gz}.xz"
fi
done' zsh {} +
Если вы предпочитаете, чтобы он был кратким, и готовы игнорировать некоторые из этих потенциальных проблем, в zsh
, вы могли бы сделать
for f (./**/*.gz(D.)) {gunzip < $f | xz > $f:r.xz && rm -f $f}
Вы можете сделать это с помощью find и parallel
parallel -0 'gzip -cd '{}' | xz > '{.}'.xz; rm '{}'' < <(find basedir -iname \*gz -print0)
Шаги завершены:
find basedir/ -type f -name '*.dat.gz'|while read -r line; do
gzip -cd "$line" | xz > ${line%.gz}.xz
rm "$line"
done