Коллекция сниппетов кода#

Арифметика#

Получить случайные числа в диапозоне от 0 до 100:

echo $((0 + $RANDOM % 100))

Дата/время#

Преобразование времени UNIX:

# Получить текущее время в UNIX:
date +%s
# Преобразовать время в UNIX:
date -d 'Tue Sep 14 06:59:34 AM MSK 2021' +%s
# Преобразовать UNIX в обычный формат:
date -d @1631591974
# Преобразовать UNIX в указанный формат:
date -d @1658950892 +'%d %b %Y %H:%M:%S %z'

sed#

Удалить строку номер n:

n=1; sed "${n}d" file.txt

Удалить строку, содержащую паттерн:

pattern="PATTERN"; sed "/${pattern}/d" file2.txt

Удалить строки до конца файла начиная со строки номер n:

n=4; sed "${n},\$d" file.txt

Удалить строки до конца файла начиная со строки, содержащей паттерн:

pattern="PATTERN"; sed "/${pattern}/,\$d" file.txt

Удалить строки от начала файла до строки, содержащей паттерн:

pattern="PATTERN"; sed "1,/${pattern}/{d}" file.txt

Удалить n строк с начала файла:

n=3; sed "1,$n{d}" file.txt

Удалить n строк с конца файла:

n=3; tac file.txt | sed "1,$n{d}" | tac

Удалить n строк до строки номер m (со 2-й по 6-ю):

n=2; m=6; sed "$n,$m{d}" file.txt

Напечатать строку str num раз:

printf %"$num"s | sed "s% %$str%g"; echo

Ещё:

awk/gawk#

Печатать все слова до конца строки начиная с шестого слова:

cat file.txt | awk '/pattern/ {for(i=6;i<=NF;i++){printf "%s ", $i}}'

Напечатать конкретную строку (6-ую):

cat file.txt | awk 'NR==6 {print $0}'

Получить объём занятой процессом памяти в MB:

ps -ylC mysqld | awk '{x += $8;y += 1} END {print "Average Proccess Size (MB): "x/((y-1)*1024)}'

Получить сумму чисел в 1-м столбце:

cat file.txt | awk '{SUM+=$1} END {print SUM}'

Напечатать строки, в которых 1-й столбец содержит число больше 300-т (если в столбце строка, то она тоже попадёт в выборку):

cat file.txt | awk '{if ($1 > 300) print $0}'

Удалить подстроку, найденную по регулярке PATTERN из STRING. Здесь используется передача паттерна через переменную Bash. В случае, если код выполняется неитерактивно для экранирования спецсимволов может потребоваться указывать дополнительный бэкслэш в паттерне. Функция sub() заменяет только первое вхождение, для замены всех надо использовать gsub().

PATTERN='regexp'  # регулярка без операторных скобок '/' '/'
echo "$STRING" | awk -v pattern="$PATTERN"\
                  'match($0, pattern, matches)\
                  {
                      ext=matches[0]"$";
                      sub(ext, "");
                      print $0
                  }'

Напечатать последний результат поиска по регулярке regexp без учёта регистра:

awk 'BEGIN {IGNORECASE=1} /regexp/ {m=$0} END {print m}'

Разное#

Глоб для захвата обычных и скрытых файлов:

echo * .[^.]*

Перенести все файлы включая скрытые из ./subdir на текущий уровень:

mv ./subdir/{*,.[^.]*} .

Добавить строку в начало файла:

echo Header | cat - file.txt > file.txt.new

Распаковка многотомного архива:

cat 1.tar.gz 2.tar.gz | tar -xz

Получить последний символ из строки (ещё интересности: https://unix.stackexchange.com/questions/144298/):

variable=string
echo ${variable: -1}  # g
# или
echo "string" | tail -c2

Удалить пробелы в строке:

str='one two'; echo ${str//[[:blank:]]/} # onetwo
# или
echo 'one two' | sed 's/ //g' # onetwo

Найти все файлы с длиной имени от 3 до 5 символов не учитывая расширение (точки и пробелы в именах учитываются):

find . -type f -regextype posix-egrep -regex ".*/(.{3,5})\.([^\.]+)$"

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

# Может быть полезно при сборке ПО для указания параметров для ./configure
echo $(<list.txt)  # без кавычек

Получить директорию, в которой размещён скрипт из самого скрипта:

# https://stackoverflow.com/questions/59895
DIR="$(dirname "$(realpath "$0")")"

Добавить BOM в начало файла:

sed -i '1s/^/\xef\xbb\xbf/' .htaccess

Ожидание ввода:

echo "Press RETURN to continue, or ^C to cancel."
read -e ignored

Задать переменные из строки:

str='my:awesome:string'
IFS=: read v1 v2 v3 <<< "$str"
# или через eval:
# eval $(<<< "$str" awk -F: '{print "v1=" $1 ";v2=" $2 ";v3=" $3}')
echo "$v1"  # my
echo "$v2"  # awesome
echo "$v3"  # string

Получить список IPv4 адресов со всех интерфейсов:

ip -4 -o addr show | grep -P -o "(?<=inet )\d+\.\d+\.\d+\.\d+"

Конвертировать WMA в MP3 320 kbps c удалением исходного файла:

for file in *.wma; do ffmpeg -i "${file}" -acodec libmp3lame -ab 320k "${file//\.wma/\.mp3}"; rm -f -- "$file"; done

Сгенерировать случайный пароль:

< /dev/urandom tr -dc 'a-zA-Z0-9\-_=+%$@~`*^&()[]{}#:;/\?\\,\.' | head -c36; echo
date | sha1sum | sed 's/[ -]//g'

Отфильтровать строки лога nginx, в которых есть ошибки 4xx-5xx, отсортировать их по количеству запросов с уникального IP и вывести в виде таблицы <кол-во запросов>|<код>|<IP-адрес>:

cat access.log | awk '$9 ~ /[4-5][0-9][0-9]/ { print $9" " $1 }' | uniq -c | sort -r | head

Бэкап отдельных файлов с сохранением структуры каталогов:

find ./*/public_html/stolbiki-parkovochnye -type f -name 'index.php' -print0 | xargs -0 cp --parents --target-directory ./tmp/backup

Следющая команда позволит скопировать в одну папку однимённые файлы. Если в папке newtest/ уже существует file.txt, то новый будет назван file.txt.~1~ и т.д.:

find ./test/ -type f -name "*.txt" -exec cp --backup=t {} ./newtest \;

Однострочник для переименования файлов с битыми именами. Преобразовывает имена файлов из cp1251 в utf8. Скрипт пропускает латинские имена и имена содержащие нормальную кириллицу. Пример плохого имени файла (вывод ls): ''$'\301\345\347''-'$'\350\354\345\355\350''-1-1-150x150.jpg'

echo -e "\n\e[31;1mRENAMED:\e[0m"; for filename in `find . -type f`; do if [[ ! $(grep -P '[^[:ascii:]]' <<< "$filename") ]] && [[ ! $(grep -vIP '[^[:ascii:]]' <<< "$filename") ]]; then new_name="$(printf '%b' "$1" | iconv -f cp1251 -t utf8 -o - <<< "$filename")"; echo -e "$filename \e[31m->\e[0m $new_name"; mv "$filename" "$new_name"; fi; done

Однострочник для массового переименования файлов с сохранением оригинальных расширений. Новые имена будут иметь числовое имя из 4-х знаков начиная от 0001.

num=1; for file in *; do new="$(printf "%04d.%s" "$num" "${file##*.}")"; mv -v -- "$file" "$new"; num=$((num+1)); done