Как я могу распаковать несколько файлов tar по отдельности с помощью одной команды?

Время аренды хранится в одном из файлов /var/log , но какой из них зависит от дистрибутива. Следующая команда

 cd /var/log && grep -nriIl dhclient 

находит все файлы с упоминанием dhclient , а в моем случае (Debian )видно, что файл syslog:

# grep -nirIl dhclient
installer/syslog
syslog
syslog.1
kern.log.1
audit/audit.log.4
audit/audit.log.2
audit/audit.log.1
audit/audit.log.3

Тогда я получаю:

# grep dhclient syslog
Jul  4 08:30:23 hague dhclient[1357]: DHCPREQUEST of 192.168.73.66 on eth0 to 192.168.73.1 port 67 (xid=0x7251b5d5)
Jul  4 08:30:23 hague dhclient[1357]: DHCPACK of 192.168.73.66 from 192.168.73.1
Jul  4 08:30:23 hague dhclient[1357]: bound to 192.168.73.66 -- renewal in 18682 seconds.
Jul  4 13:41:45 hague dhclient[1357]: DHCPREQUEST of 192.168.73.66 on eth0 to 192.168.73.1 port 67 (xid=0x7251b5d5)
Jul  4 13:41:45 hague dhclient[1357]: DHCPACK of 192.168.73.66 from 192.168.73.1
Jul  4 13:41:45 hague dhclient[1357]: bound to 192.168.73.66 -- renewal in 14622 seconds.

, который дает ответ, который вы ищете.

0
08.09.2019, 06:04
2 ответа

Вы не можете использовать {}в подстановке команд (, вызывая basename), так как это выполняется до того, как будет вызвано , даже xargs. Это означает, что tarпопытается изменить каталог на каталог с именем{}(буквально )для каждого архива.

Используйте цикл for, в xargsнет необходимости. например.

for t in *.tar ; do
  bn="$(basename "$t".tar)"
  mkdir -p "$bn"
  tar -xvf "$t" -C "$bn"
done

См. также:Почему не разборls(и что делать вместо )?

3
28.01.2020, 02:22

Причина, по которой ваша команда не работает, заключается в том, что подстановка команды (бита, который вы написали с помощью обратных кавычек ), будет выполнена один раз, прежде чем xargsдаже запустится.

Поскольку вы пометили это как xargs, я решил дать решение, основанное на xargs-.

Во-первых, чтобы распаковать один из ваших tarархивов, вы можете использовать

dir=${archive%.tar}
mkdir -- "$dir" && tar -x -f "$archive" -C "$dir"

... при условии, что $archiveсодержит имя файла архива tarи что архив является простым (не сжатым ).

Очевидно, вы могли бы зациклить это с помощью

for archive in *.tar; do
    dir=${archive%.tar}
    mkdir -- "$dir" && tar -x -f "$archive" -C "$dir"
done

, но это не позволило бы нам использовать некоторые из обычных (, хотя и не -стандартных )функций xargs, таких как параллельное выполнение нескольких команд.

Чтобы запустить наши исходные команды, по четыре за раз, имена tarархивов должны быть введены в xargsна его стандартном вводе.

Мы можем сделать это с помощью

printf '%s\n' *.tar | xargs...

Это, очевидно, предполагает, что ни один архив не имеет имени, содержащего встроенные символы новой строки, но вы можете обойти это, используя

printf '%s\0' *.tar | xargs -0...

, если ваша реализация xargsподдерживает не -стандартную -0опцию для чтения аргументов, завершающихся нулем -.

Чтобы запустить распаковку из xargs, было бы проще сделать это в дочерней оболочке sh -c:

printf '%s\0' *.tar |
xargs -0 -P 4 -I {} sh -c 'dir=${1%.tar}; mkdir -- "$dir" && tar -x -f "$1" -C "$dir"' sh {}

В сценарии оболочки sh -c$1будет таким же, как $archiveв нашей исходной команде, и сценарий будет запускаться один раз для каждого архива. Параметр -P 4для xargsбудет запускать четыре извлечения параллельно, если ваша реализация xargsподдерживает параметр -P.

0
28.01.2020, 02:22

Теги

Похожие вопросы