Я предпочитаю использовать mpack для отправки вложений в формате MIME
как в:
mpack -s "message" file email@example.com
Name
mpack - pack a file in MIME format Synopsis
mpack [ -s subject ] [ -d descriptionfile ] [ -m maxsize ] [ -c content-type ] file address... mpack [ -s subject ] [ -d descriptionfile ] [ -m maxsize ] [ -c content-type ] -o outputfile file mpack [ -s subject ] [ -d descriptionfile ] [ -m maxsize ] [ -c content-type ] -n newsgroups file Description
The mpack program encodes the the named file in one or more MIME messages. The resulting messages are mailed to one or more recipients, written to a named file or set of files, or posted to a set of newsgroups.
Вы можете адаптировать исходное решение для чтения файлов до тех пор, пока оно не найдет тот, который не исключен:
while IFS= read -r -d '' line
do
file="${line#* }"
if [ "$file" = './my-excluded-directory' ]
then
continue
fi
[do stuff with $file]
break
done < <(find. -maxdepth 1 -type d -printf '%T@ %p\0' | sort -z -n)
(-d ''
эквивалентен оригиналу, потому что в строках не может быть символов NUL.)
read
Работа с длинным списком медленная, и @mosvy прав, что вы можете выполнять фильтрацию с довольно неприятным find
синтаксисом:
IFS= read -r -d '' < <(find. -maxdepth 1 -type d \( -name 'my-excluded-directory' -prune -false \) -o -printf '%T@ %p\0' | sort -z -n)
file="${REPLY#* }"
# do something with $file here
Нет, это решение не идеально, потому что оно зависит от множества крайне не -переносимых функций (find -printf
, sort -z
, read -d
и т. д. ).
Мое решение также не идеально, так как оно зависит от оператора -ot
из test
(, который проверяет, старше ли файл, чем другой ); однако, кажется, что он гораздо лучше поддерживается (*bsd, busybox, solaris, linux ).
# usage with_2nd_oldest 'command' files...
with_2nd_oldest(){
cmd="$1"; shift
oz="$1"; shift; oy=$1
for f; do
if [ "$f" -ot "$oz" ]; then oy=$oz oz=$f
elif [ "$f" -ot "$oy" -a "$f" != "$oz" ]; then oy=$f
fi
done
$cmd "$oy"
}
$ with_2nd_oldest 'echo rm -fr --' dir/*/
Это также может обрабатывать повторяющиеся аргументы:
$ for i in `seq 1 9`; do mkdir -p $i; sleep 1; done
$ with_2nd_oldest echo 7 7 1 1 3 3 2 2 8 9 5 1
2
Для другого более старого вопроса, где требовался самый старый файл/каталог, это еще проще:
with_oldest(){
cmd="$1"; shift
oz="$1"; shift
for f; do test "$f" -ot "$oz" && oz=$f; done
$cmd "$oz"
}
Оба могут быть тривиально адаптированы для пропуска произвольных путей или для чтения списка файлов из стандартного ввода.
Сzsh
:
set -o extendedglob # best in ~/.zshrc
rm -rf -- ^that-folder-to-keep(D/Om[1])
С решением, предоставленным в этом другом вопросе и ответе:
IFS= read -r -d '' line < <(
find. -maxdepth 1 \
! -name that-folder-to-keep \
-type d -printf '%T@ %p\0' 2>/dev/null | sort -z -n) &&
rm -rf "${line#* }"
Если вы хотите удалить второй по старшинству:
zsh
:
rm -rf -- *(D/Om[2])
Утилиты GNU:
{ IFS= read -r -d '' line &&
IFS= read -r -d '' line &&; } < <(
find. -maxdepth 1 \
-type d -printf '%T@ %p\0' 2>/dev/null | sort -z -n) &&
rm -rf "${line#* }"
#!/bin/bash
while IFS= read -r -d '' line
do
file="${line#* }"
if [ "$file" = './Development_Instance' ]
then
continue
fi
if [ "$file" = './lost+found' ]
then
continue
fi
echo $file
break
done < <(find. -maxdepth 1 -type d -printf '%T@ %p\0' | sort -z -n)
Вот как я справился. Я знаю, что это не самый элегантный способ сделать это. Это просто делает вещь для меня.
Одним из «хитрых» способов сделать это было бы изменение временной метки исключенного каталога в начале и восстановление его временной метки в конце:
$ cd "$(mktemp --directory)"
$ echo foo > example.txt
$ modified="$(date --reference=example.txt +%s)" # Get its original modification time
$ touch example.txt # Set the modification time to now
[delete the oldest file]
$ touch --date="@$modified" example.txt # Restore; the "@" denotes a timestamp
Применяются обычные предостережения:
touch --reference="$path" "${path}.timestamp"
, чтобы сохранить метку времени в реальном файле и восстановить с помощью touch --reference="${path}.timestamp" "$path"
.