Intereting Posts
Как я могу заставить ядро ​​Ubuntu терпеть неудачу при установке / и перейти в оболочку для восстановления initramfs? Установите фокус на новое окно неспособность установить связь с использованием grabserial Почему не находит. -delete удалить текущий каталог? Удаленный хост pingable от Mac, но не от виртуальной машины Virtualbox Как ограничить установку xorg одним видеодрайвером? как открыть чей-то общий календарь на thunderbird openvpn мост к сети Ethernet Почему эхо соответствует некоторым файлам дважды? Ubuntu: Как правильно настроить DNS-серверы в / etc / network / interfaces для resolvconf? Эффективность рабочего стола влияет на производительность программы? Не разрешено доступ к моим файлам в $ HOME в tmux после выхода из системы и входа в систему PROMPT_DIRTRIM не работает Список версий программного обеспечения по умолчанию для данного выпуска Ubuntu Удалить большое количество каталогов под верхним уровнем

файлы списка tar, перерыв в первом файле

Я использовал следующий фрагмент, извлеченный из аналогичного сообщения – https://unix.stackexchange.com/a/101273/212793 – чтобы получить имя файла из файла tar.gz :

 tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' 

Для моего случая мне нужен только один конкретный файл, поэтому я использую что-то вроде:

 tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' | grep -e "^..*my-file-name\\.ext$" 

Ключевой частью является то, что мой .tar.gz очень большой и содержит много файлов. Тем не менее, каждый из них имеет аналогичный «хэш», добавленный к началу (отсюда часть ^..* моего регулярного выражения grep'd).

Таким образом, файлы могут выглядеть так:

 - 4b77e4e1_file-a.ext - 4b77e4e1_file-b.ext - 4b77e4e1_file-c.ext # ect. 

Я заметил, что команда для получения всех файлов ( tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' ) передает результат.

Моя мысль заключается в том, что если я могу «сломать» поток, а затем извлечь эту первую хеш-часть, я смогу создать свое имя файла, которое мне в итоге понадобится, без необходимости прокручивать все содержимое файла .tar.gz .

Поэтому мой вопрос заключается в том , как я могу «разбить» awk на его первом выходе, в отличие от ожидания завершения всей команды (которая занимает несколько минут) и grepping результата, чтобы получить имя файла, которое в конечном итоге я хочу .

EDIT : Похоже, я действительно хочу сломать tar , так как просто exit после первого результата не изменит время выполнения.

попробуйте что-нибудь вроде

  tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /my-filename$/ {print $NF ; exit }' 

или

  tar tzf "archive.tar.gz" | awk -F/ 'substr($NF,4,11) == "my-filename" {print $NF ; exit }' 

(где 4 и 11 должны совпадать с фактическим именем файла).

Вы можете сказать AWK выйти после печати что-то:

 awk -F/ '$NF != "" { print $NF; exit }' 

Поскольку вы ищете определенное имя файла:

 awk -F/ '/my-file-name\.ext$/ && $NF != "" { print $NF; exit }' 

Тест $NF избыточен, тогда:

 awk -F/ '/my-file-name\.ext$/ { print $NF; exit }' 

Если одна из программ в конвейере выйдет, то программы слева от нее также выйдут. Как это работает:

  • В foo | bar foo | bar , выходы из bar .
  • Выход из процесса закрывает считываемый конец трубы.
  • Когда foo пытается записать в трубу, он получает сигнал SIGPIPE.
  • foo умирает.

Это предполагает, что foo не защищен от SIGPIPE; программы могут это сделать, но типичные программы командной строки этого не делают.

Поскольку вы хотите только один матч, сделайте выход awk, как только он найдет интересующую вас строку:

 tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}' 

или (здесь не очень выгодно)

 tar tzf "archive.tar.gz" | sed -n '/[^/]my-file-name\.ext$/ {s!.*/!!; q}' 

или, придерживаясь вашего более сложного подхода использования grep отдельно от awk

 tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' | grep -e "^..*my-file-name\\.ext$" | head -n 1 

Выход из считывателя приводит к тому, что tar выходит, когда он записывает в следующий канал, что может занять некоторое время из-за буферизации вывода . (Это займет особенно много времени, если на трубе будет более двух процессов, поскольку для каждого из них будет получена задержка SIGPIPE.) После выхода awk find будет тратить немного времени на чтение архива и заполнение следующего буфера с именами файлов, затем, наконец, попытайтесь записать буфер и быть убитым с помощью SIGPIPE. Для этого приложения, скорее всего, будет быстрее переключить tar для буферизации строк для вывода, что вы можете сделать с stdbuf :

 stdbuf -oL tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}' 

В качестве альтернативы вы можете договориться о том, чтобы убить программу tar, когда awk выйдет, но это сложнее.

 sh -m 'tar tzf "archive.tar.gz" | { awk -F/ "$0"; kill -TERM -$$; }' '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}' [ $? -eq 143 ]