Найти exec '{}' не доступно после>

Вы должны быть в состоянии выполнить sudo systemctl edit apache2.service и ввести пользовательские переопределения в файл, как показано ниже:

[Service]
Restart=on-failure
8
14.11.2018, 15:27
5 ответов

Вы можете использовать bash -cв команде find -execи использовать позиционный параметр с командой bash:

find. \( -name '*.jpg' -o -name '*.jpeg' \) -exec bash -c 'cjpeg -quality 80 "$1" > "$(dirname "$1")/optimized_$(basename "$1")"' sh {} \;

Таким образом {}обеспечивается $1.

shперед {}сообщает внутренней оболочке ее «имя», строка, используемая здесь, используется, например, в. Сообщения об ошибках. Подробнее это обсуждается в этом ответе на stackoverflow .

13
27.01.2020, 20:08

Создать скрипт cjq80:

#!/bin/bash
cjpeg -quality 80 "$1" > "${1%/*}"/optimized_"${1##*/}"

Сделать его исполняемым

chmod u+x cjq80

И используйте его в -exec:

find. \( -name '*.jpg' -o -name '*.jpeg' \) -exec cjq80 '{}' \;
1
27.01.2020, 20:08

У вас есть ответ (https://unix.stackexchange.com/a/481687/4778), но вот почему.

Перенаправление >, а также каналы |и расширение $выполняются оболочкой до выполнения команды. Поэтому стандартный вывод перенаправляется на optimized_{}до запуска find.

8
27.01.2020, 20:08

cjpeg имеет опцию, позволяющую записывать в именованный файл, а не в стандартный вывод. Если ваша версия findподдерживает параметр -execdir, вы можете воспользоваться этим, чтобы сделать перенаправление ненужным.

find. \( -name '*.jpg' -o -name '*.jpeg' \) \
  -execdir cjpeg -quality 80 -outfile optimized_'{}' '{}' \;

Обратите внимание, :это на самом деле предполагает BSD-версию find, которая удаляет начальный ./из имени файла при расширении до {}. (Или, наоборот, GNUfindдобавляет./к имени. Нет стандарта, чтобы сказать, какое поведение является «правильным».)

3
27.01.2020, 20:08

Перенаправление необходимо заключать в кавычки, чтобы его не интерпретировала текущая оболочка.
Но его цитирование также позволит избежать перенаправления вывода команды.
Известным решением этого является вызов оболочки:

find. -name '*.jpg' -exec sh -c 'echo "$1" >"$1".new' called_shell '{}' \;

В этом случае перенаправление(>)указано в кавычках в текущей оболочке и корректно работает внутри вызываемой оболочки. called_shellиспользуется как $0параметр (имя )дочерней оболочки(sh).

Это хорошо работает, если к имени файла добавляется суффикс, но не при использовании префикса. Чтобы префикс работал, вам нужно как удалить ./, который находит перед именами файлов с ${1#./}, так и использовать опцию -execdir.

Вы можете (или не )использовать параметр -iname, чтобы файлы с именами *.JPGили *.JpGили другими вариантами также были включены.

find. \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
     cjpeg -quality 80 "$1" > optimized_"${1#./}"
     ' called_shell '{}' \;

И вы можете (или не можете )вызывать оболочку один раз для каталога, а не один раз для файла, добавив цикл(for f do … ; done+в конце:

find. \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
     for f; do cjpeg -quality 80 "$f" > optimized_"${f#./}"; done
     ' called_shell '{}' \+

И, наконец, поскольку cjpegможет напрямую записывать в файл, перенаправления можно было бы избежать, поскольку:

find. \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
     for f; do cjpeg -quality 80 "$f" -outfile optimized_"${f#./}"; done
     ' called_shell '{}' \+
3
27.01.2020, 20:08

Теги

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