Вашим вопросом является на самом деле Bash FAQ № 89: просто добавьте Я брал на себя смелость согласовывания Вашего сценария для Вас, потому что это содержит много потенциальных ошибок. Несколько важных моментов: Имена файлов хитры для обработки, потому что большинство файловых систем позволяет им содержать все виды непечатных символов, которые нормальные люди рассматривали бы как мусор. Создание упрощения предположений как "имена файлов содержит только 'нормальные' символы", имеет тенденцию заканчиваться хрупкие сценарии оболочки, которые, кажется, работают над "нормальными" именами файлов и затем повреждают день, они сталкиваются с особенно противным именем файла, которое не следует за предположениями сценария. С другой стороны, правильно обрабатывающие имена файлов могут быть таким беспокойством, что можно найти его не стоящим усилия, если шанс обнаружения со странным именем файла, как ожидают, будет близким нулем (т.е. Вы только используете сценарий на своих собственных файлах, и Вы даете Вашим собственным файлам "простые" имена). Иногда возможно избежать этого решения в целом, не анализируя имена файлов вообще. К счастью, это возможно с Используя Использовать Избегайте использования ПРОПИСНЫХ имен переменной. То пространство имен обычно резервируется оболочкой для особых целей (как И теперь, без дальнейшей суматохи, вот очищенный сценарий для Вас: Примечание: Я использовал POSIX предотвратить
ffmpeg
от чтения его стандартного входа.find(1)
-exec
опция. Просто помещенный {}
в аргументе -exec
и Вы не должны волноваться о парсинге find
вывод.sed
или другие внешние процессы, чтобы сделать операции простой строки как разделение расширений и префиксов неэффективны. Вместо этого используйте расширения параметра, которые являются частью оболочки (никакой внешний процесс не означает, что это будет быстрее). Некоторые полезные статьи о предмете упоминаются ниже:$( )
, и не используйте ``
больше: Bash FAQ 82.PATH
), так использование его для Ваших собственных переменных является плохой идеей.#!/bin/sh
logfile=encodemp4ize.log
echo "Started at $(date)." > "$logfile"
rsync -avz --exclude '*.flv' flvs/ mp4s/
find flvs/ -type f -name '*.flv' -exec sh -c '
for flvsfile; do
file=${flvsfile#flvs/}
< /dev/null ffmpeg -i "$flvsfile" -vcodec libx264 -vprofile high \
-preset slow -b:v 500k -maxrate 500k -bufsize 1000k \
-threads 0 -acodec libfaac -ab 128k \
"mp4s/${file%flv}"mp4
printf %s\\n "$flvsfile MP4 done." >> "$logfile"
done
' _ {} +
sh
потому что Вы не использовали или нуждаетесь в любом bash
- определенные функции в Вашем оригинале.
sed 's/.$//'
Удалить последний знак.
Но в этом конкретном случае, Вы могли также сделать:
df -P | awk 'NR > 1 {print $5+0}'
С арифметическим выражением ($5+0
) мы вызываем awk
для интерпретации 5-го поля как числа и чего-либо после, число будет проигнорировано.
Отметьте тот GNU df
(Ваш -h
уже расширение GNU, хотя не нужный здесь) может также быть сказан только произвести процент использования диска:
df --output=pcent | tail -n +2 | tr -cd '0-9\n'
(хвост пропускает заголовки, и TR удаляет все кроме цифр и разделителей строки).
На Linux см. также:
findmnt -no USE%
С sed
, это довольно легко:
$ cat file
Use%
22%
1%
1%
59%
51%
63%
5%
$ sed 's/.$//' file
Use
22
1
1
59
51
63
5
Синтаксис s(ubstitute)/search/replacestring/
. .
указывает на любой символ, и $
конец строки. Так .$
удалит последний знак только.
В этом случае Ваша полная команда посмотрела бы:
df -h | awk '{ print $5}' | sed 's/.$//'
sed
избыточно: в этом можно выполнить awk
: df -h | awk '{gsub(/%/,""); print $5}'
– jasonwryan
15.07.2013, 09:33
В awk Вы могли сделать один из
awk '{sub(/%$/,"",$5); print $5}'
awk '{print substr($5, 1, length($5)-1)}'
другой подход:
mapfile -t list < <(df -h)
printf '%s\n' "${list[@]%?}"
Превратите его в функцию:
remove_last() {
local char=${1:-?}; shift
mapfile -t list < <("$@")
printf '%s\n' "${list[@]%$char}"
}
Затем назовите его как это:
remove_last '%' df -h
mapfile
bash4 функция.
Выгода здесь - то, что необходимо предоставить символ для удаления; если Вы хотите, чтобы это просто было независимо от того, что последний знак, оказывается, затем, необходимо передать '?'
или ''
. кавычки требуются.
У меня есть два решения:
cut: echo "somestring1" | rev | cut -c 2- | rev
Здесь вы реверсируете строку, вырезаете строку из 2-го символа и снова реверсируете.
sed : echo "somestring1" | sed 's/.$//'
Здесь вы будете искать регулярное выражение . $
, что означает любые символы, за которыми следует последний символ, и заменить его на ноль //
(между двумя косая черта)
Попробуйте следующее:
df -h | awk '{ print $5 }' | sed "s/%//"
Обычное использование: (т.е.)
VALUE=987654321
echo X123456789X | sed "s/123456789/${VALUE}/"
Ответ должен быть: X987654321X
sed -ie '$d' filename
here -i is to write changes
e means expression
$ means last line
d means delete
Note:Without -e option $ wont work
Дополнительно:Чтобы удалить 1-ю и последнюю строку, используйте sed -ie '1d;$d'
имя файла
Знаете ли вы, что head
и tail
могут работать посимвольно, а не построчно?
$ printf "I don't like periods." | head -c-1
I don't like periods
(Кстати, printf
используется здесь для предотвращения печати символа «новой строки» в конце строки. Если в вашем выводе есть символ новой строки, и вы хотите удалить его, а также последний символ пробела, отличный от -, используйтеhead -c-2
).
Это в основном то же самое, что и решение "Гуру" с использованием cut
, но без причудливых rev
туда и обратно, которые им нужно использовать, потому что cut
не имеет синтаксиса для "последних n вещей".
Чтобы перебрать поток строк и удалить последний символ каждой, можно сделать что-то вроде этого:
some-command | while read line; do echo $(head -c-2 <<<"$line"); done
{print +$5}
будет работать также... – jasonwryan 15.07.2013, 09:37awk
реализации, где это не работает, где+
унарный оператор просто проигнорирован и не вызывает преобразование строк к числовому. – Stéphane Chazelas 11.09.2015, 11:49