Вы должны быть в состоянии выполнить sudo systemctl edit apache2.service
и ввести пользовательские переопределения в файл, как показано ниже:
[Service]
Restart=on-failure
Вы можете использовать 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 .
Создать скрипт cjq80:
#!/bin/bash
cjpeg -quality 80 "$1" > "${1%/*}"/optimized_"${1##*/}"
Сделать его исполняемым
chmod u+x cjq80
И используйте его в -exec:
find. \( -name '*.jpg' -o -name '*.jpeg' \) -exec cjq80 '{}' \;
У вас есть ответ (https://unix.stackexchange.com/a/481687/4778), но вот почему.
Перенаправление >
, а также каналы |
и расширение $
выполняются оболочкой до выполнения команды. Поэтому стандартный вывод перенаправляется на optimized_{}
до запуска find
.
cjpeg
имеет опцию, позволяющую записывать в именованный файл, а не в стандартный вывод. Если ваша версия find
поддерживает параметр -execdir
, вы можете воспользоваться этим, чтобы сделать перенаправление ненужным.
find. \( -name '*.jpg' -o -name '*.jpeg' \) \
-execdir cjpeg -quality 80 -outfile optimized_'{}' '{}' \;
Обратите внимание, :это на самом деле предполагает BSD-версию find
, которая удаляет начальный ./
из имени файла при расширении до {}
. (Или, наоборот, GNUfind
добавляет./
к имени. Нет стандарта, чтобы сказать, какое поведение является «правильным».)
Перенаправление необходимо заключать в кавычки, чтобы его не интерпретировала текущая оболочка.
Но его цитирование также позволит избежать перенаправления вывода команды.
Известным решением этого является вызов оболочки:
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 '{}' \+