Ответ Michael Mrozek будет работать, если Вы не будете заботиться об удалении команд от текущей сессии. Если Вы делаете, необходимо записать в файл истории прежде, чем сделать операции в его сообщении путем выполнения history -a
.
Кроме того, после удаления записей, которые Вы хотите из своего файла истории, можно перезагрузить его путем издания history -c
, затем history -r
.
Этот сценарий заархивирует, затем дополнительно удаляют все папки, содержащие "*.txt" файлы и ничто иное.
folders=$(find . -type d -exec sh -c 'cd "$1";[ "$(ls *.txt 2>/dev/null)" ] \
&& [ -z "$(ls -ad * | grep -v '\.txt$')" ] && echo "$1"' sh {} \;)
echo "$folders" | zip -r@ archive && echo "$folders" | while read folder; do
echo "will remove $folder"
# Uncomment next line for the folder to be removed
# rm -rf "$folder"
done
Править: вот решение, которое создает отдельные zip-файлы:
find . -depth -type d -exec sh -c '
cd "$1" || exit
[ "$(ls ./*.txt 2>/dev/null)" ] &&
[ -z "$(ls -ad ./* | grep -v '\.txt$')" ] &&
(
b=$(basename "$1")
cd ..
zip -r "$b.zip" "$b" && rm -rf "$b"
)' sh {} \;
Вот более простой подход: Использовать find
получить список каталогов; в каждом каталоге проверьте если список .txt
файлы совпадают со списком всех файлов. Если это, идите вперед и архивируйте его.
Это сделано намного легче тем, что заархивированные папки не могут содержать подпапки. Я предполагаю, что ни один из Ваших файлов или папок не начинается с точки; если это не верно, сообщите мне, и я добавлю необходимые проверки.
for DIR in `find . -type d -print`
do
TXT=`echo "$DIR"/*.txt`
ALL=`echo "$DIR"/*`
if [ "$TXT" == "$ALL" ]
then
echo only txt: $DIR
# zip "$DIR"
fi
done
for DIR in $(find …)
только работы, если ни одни из имен каталогов не содержат пробел или \[*?
.
– Gilles 'SO- stop being evil'
09.12.2013, 00:05
Следующий отрывок пересекает все подкаталоги текущего каталога. Если это находит каталог, содержащий только подкаталоги или файлы с .txt
расширение, это архивирует каталог и удаляет его.
find . -type d -exec sh -c '
if [ -z "$(find "$0" ! -type d ! -name "*.txt" | head -n 1)" ]; then
zip -r "$0.zip" "$0" && rm -r "$0"
else
exit 1
fi
' {} \; -prune
find
не может возвратить пустую строку с -type d
учитывая факт текущий каталог будет всегда соответствовать. Вы имеете .txt
тест инвертировал (должен быть ! -name "*.txt"
). Zip-файл будет содержать целую иерархию, в то время как OP мог бы предпочесть только единственный каталог. Вы оба отсутствовали для передачи {}
и пропущенный для окончания -exec
действие.
– jlliagre
09.12.2013, 13:05
Следующий сценарий рекурсивно находит каталоги и выполняет zip на них, если они содержат только .*txt
файлы. Это работает как это: все подкаталоги проверяются с шаблоном на non-txt файлы и шаблоном для txt-файлов. Если существуют какие-либо txt подобранные файлы и нет никаких других типов подобранных файлов, каталог заархивирован и уничтожен.
#!/bin/bash
shopt -s dotglob nullglob extglob
for dir in $(find "$1" -type d); do
non_txt=("$dir"/!(*.txt)); txt=("$dir"/+(*.txt))
if ((${#txt[@]} && ! ${#non_txt[@]})); then
zip -r "$dir.zip" "$dir" && rm -r "$dir"
fi
done
Другой вариант, который рассматривает имена каталогов с \[*?
символы в них:
#!/bin/bash
find "$1" -depth -type d -exec sh -c '
shopt -s dotglob nullglob extglob
non_txt=("$1"/!(*.txt)); txt=("$1"/+(*.txt))
if ((${#txt[@]} && ! ${#non_txt[@]})); then
zip -r "$1.zip" "$1" && rm -r "$1"
fi
' sh {} \;
for dir in $(find …)
только работы, если ни одни из имен каталогов не содержат пробел или \[*?
.
– Gilles 'SO- stop being evil'
09.12.2013, 00:04
-exec
основной, как в ответе jlliagre.
– Gilles 'SO- stop being evil'
09.12.2013, 00:09
-exec
, хотя я не могу действительно сказать два результата независимо, рассмотрев каталоги с этими символами, кроме пробела, который не обрабатывается хороший for i in $(find …)
.
–
09.12.2013, 01:05
find ... -print0 | while read -d $'\0' i; do stuff with "$i"; done
- должно быть пуленепробиваемым, и я думаю, что это выглядит более опрятным, чем зубрежка все это в - должностное лицо.
– evilsoup
09.12.2013, 02:29