Если вы хотите перенаправить вывод команды с -exec
, лучше выполнить команду shell ; Попробуйте следующий синтаксис в вашем случае:
find -name ".vimrc" -exec sh -c 'echo "set number" >> {}' \;
Это будет работать, как ожидалось.
Из руководства ...
[- d exdir]
Необязательный каталог для извлечения файлов. По умолчанию все файлы и подкаталоги воссоздаются в текущем каталоге; Параметр -d разрешает извлечение в произвольный каталог (всегда при условии, что у кого-то есть разрешение на запись в каталог). Эта опция не обязательно должна появляться в конце командной строки; он также принимается перед спецификацией zip-файла (с обычными параметрами), сразу после спецификации zip-файла или между файлом (-ами) и параметром -x. Параметр и каталог могут быть объединены без пробелов между ними, , но учтите, что это может привести к подавлению нормального поведения оболочки. В частности,
-d ~
(тильда) расширяется оболочками Unix C в имя домашнего каталога пользователя, но-d ~
рассматривается как буквальный подкаталог~
текущего каталога.
Итак ...
unzip -d new_dir zipfile.zip
Это создает каталог new_dir и извлекает из него архив, что позволяет избежать потенциального беспорядка каждый раз, даже без предварительного просмотра. Также очень полезно посмотреть man unzip
. Дополнительная справка по страницам руководства .
Ну, вы могли бы просто извлечь в подкаталог без условий и избавиться от него, если он содержит только один элемент.
Но зачем идти на здравое и простое решение (любезно предоставленное ilkkachu), если можно использовать awk
? :)
sunzip ()
{
if [ $# -ne 1 ] || ! [ -f "$1" ]
then
printf '%s\n' "Expected a filename as the first (and only) argument. Aborting."
return 1
fi
extract_dir="."
# Strip the leading and trailing information about the zip file (leaving
# only the lines with filenames), then check to make sure *all* filenames
# contain a /.
# If any file doesn't contain a / (i.e. is not located in a directory or is
# a directory itself), exit with a failure code to trigger creating a new
# directory for the extraction.
if ! unzip -l "$1" | tail -n +4 | head -n -2 | awk 'BEGIN {lastprefix = ""} {if (match($4, /[^/]+/)) {prefix=substr($4, RSTART, RLENGTH); if (lastprefix != "" && prefix != lastprefix) {exit 1}; lastprefix=prefix}}'
then
extract_dir="${1%.zip}"
fi
unzip -d "$extract_dir" "$1"
}
Quick'n'dirty. Работает с unzip
v6.0 от InfoZIP.
Вы можете адаптировать его под свои нужды, например, принимать или автоматически использовать дополнительные параметры для unzip
, или использовать другое имя для подкаталога извлечения (которое в настоящее время определяется по имени файла zip
).
О, и я только что заметил, что это обходное решение правильно справляется с двумя наиболее распространенными ситуациями (1. ZIP-файл содержит один каталог с содержимым, 2. ZIP-файл содержит множество отдельных файлов и/или каталогов), но не создает подкаталог, когда корень ZIP-файла содержит несколько каталогов, но без файлов...
Edit: Fixed. Сценарий awk
теперь сохраняет первый компонент ("префикс") каждого пути, содержащегося в ZIP-файле, и прерывается, как только обнаруживает префикс, отличающийся от предыдущего. Это позволяет перехватывать как несколько файлов, так и несколько каталогов (поскольку и те, и другие могут иметь разные имена), игнорируя при этом ZIP-файлы, в которых все содержится в одном подкаталоге.
Вы можете использовать мой скрипт, используя mv
.
mkdir downloaded
mv downloaded.zip downloaded && cd downloaded
unzip downloaded.zip && cd
Вы создадите папку (downloaded) и распакуете его в созданную папку.
Вместо того, чтобы проверять содержимое архива перед его извлечением, вы также можете извлечь его, используя unar
, что обеспечит поведение, которое вы ищете после :по умолчанию, если архив содержит один каталог верхнего -уровня, unar
извлекает его как -, в противном случае он создает каталог с именем архива и извлекает его туда. Вы можете принудительно создать каталог во всех случаях с опцией -d
.
unar
также имеет то преимущество, что поддерживает широкий спектр форматов архивов.