export LD_LIBRARY_PATH="/usr/local/lib"
echo ${LD_LIBRARY_PATH}
Часто бывает нужно добавить в переменную новый путь так, чтобы он отделялся от существующих путей символом двоеточия. Сделать это можно как-то так:
export LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}"
echo ${LD_LIBRARY_PATH}
Если изначально в переменной LD_LIBRARY_PATH
был записан путь /usr/lib
, то после добавления нового пути в переменной LD_LIBRARY_PATH
будет храниться строка:
/usr/local/lib:/usr/lib
. Но если изначально переменная LD_LIBRARY_PATH
была пустой, то после добавления в ней будет ненужное двоеточие:/usr/local/lib:
. Чтобы этого избежать, добавлять пути лучше такой командой:
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH+"${LD_LIBRARY_PATH}:"}/usr/local/lib"
echo ${LD_LIBRARY_PATH}
Данная команда выполняет в текущем интерпретаторе команды из bash-скрипта. Первый аргумент этой команды -- имя bash-скрипта, все последующие аргументы -- это аргументы bash-скрипта.
source my_script.sh
Например, для активации окружения анаконды с именем "py27" нужно выполнить
source activate py27
В этом случае команда source
выполняет скрипт activate
(путь к которому прописан в переменной PATH
) с аргументом py27
.
У команды source
есть алиас -- .
(точка). Поэтому, предыдущую команду можно было бы выполнить так:
. activate py27
Если вы предполагаете, что ваш код будут читать другие люди, то лучше не использовать точку, а писать явно команду source
.
Если же мы просто запустим скрипт:
./my_script.sh
или так:
bash ./my_script.sh
то этот скрипт выполнится в новом интерпретаторе.
Чтобы bash-скрипт завершался, если где-то произошла ошибка, добавьте в заголовок скрипта:
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
usage="script expects 2 required arguments and three optional arguments which have to be placed after required arguments.\n"
usage="${usage}Usage example:\n./$(basename "$0") input_filename output_filename [-e 'utf-8'] [-d ','] [-v]"
n_required_arguments=2
if [ "$#" -lt ${n_required_arguments} ]; then
echo -e ${usage}
exit
fi
input_filename=$1
output_filename=$2
OPTIND=$(( ${n_required_arguments} + 1 ))
delimiter=","
encoding="utf-8"
verbose=false
while getopts "d:e:v" opt
do
case $opt in
d) delimiter=$OPTARG;;
e) encoding=$OPTARG;;
v) verbose=true;;
esac
done
function list_folder() {
folder=$1
ls -alh ${folder}
}
list_folder $HOME
В этом примере вывод команды ls
используется как аргумент команды echo
:
echo $(ls -lSh $HOME)
head <(ls -lSh $HOME)
Предположим, что мы хотим сравнить два файла с помощью команды diff
. Но содержимое обоих файлов неупорядоченно, и перед сравнением файлов мы должны их отсортировать. Все можно сделать в одной строке:
diff <(sort first_file.csv) <(sort second_file.csv)
start_date='2017-01-01'
end_date='2017-03-01'
current_date=${start_date}
while [ "${current_date}" \< "${end_date}" ]; do
echo ${current_date}
current_date=$(date --date "${current_date} + 1 day" "+%Y-%m-%d")
done
Для копирования файлов используйте rsync
и только rsync
! В отличие от команды cp
rsync
выполняет умное копирование:
rsync
возобновляет копирование, если оно было прерваноrsync
не будет повторно копировать файл, если он уже скопирован
Скопировать файл можно так:
rsync -aP /source_folder/filename.csv /destination_folder/
rsync -aP user@hostname:~/source_folder/filename.csv /destination_folder/
rsync -aP -e "ssh -p 2200" user@hostname:~/source_folder/filename.csv /destination_folder/
В последней команде указана опция ssh-соединения, а именно порт 2200.
Отобразить первые/последние 20 строк файла можно следующими командами:
head -n 20 data.csv
tail -n 20 data.csv
Игнорировать первую строку файла:
tail -n +2 data.csv
Игнорировать последнюю строку файла:
head -n -1 data.csv
tar czvf archive.tar.gz ./folder
tar xzvf archive.tar.gz
Обратите внимание, что порядок опций команды tar
важен! После опции f
должно идти имя архива. Если опцию f
поменять местами, например, с опцией v
:
tar czfv archive.tar.gz ./folder
то tar
постарается создать архив с именем v
и добавить в него файл archive.tar.gz и директорию folder
. А это совсем не то, что мы хотим. Если вы чувствуете себя неуверенно при работе с опциями команды tar
, то можете писать опции полностью (быстро надоедает). Например так:
tar --create --gzip --verbose --file archive.tar.gz ./folder
Кроме сжатия алгоритмом gzip можно использовать алгоритм bzip2 (опция --bzip2
) и алгоритм lzma (опция --lzma
). Оба эти алгоритма, как правило, сжимают в разы лучше, чем gzip.
Не забывайте указывать расширение архива, соответствующее алгоритму сжатия (tar.bz2
для bzip2 и tar.lzma
для lzma).
Предположим, что у нас есть скрипт analyzer.py
, который принимает 3 параметра из командной строки:
- имя файла
- число групп точек
- индекс группы
Тогда мы можем обработать все точки в файле, запустив скрипт параллельно с помощью команды xargs
:
n_cpu=8
n_batches=100
batch_size=100000
seq 0 $(( ${n_batches} - 1))| xargs -P ${n_cpu} -n 1 analyzer.py input_data.csv ${batch_size}
Найти все файлы с расширением ".sh", находящиеся в текущей директории, или в поддиректориях, можно командой:
find ./ -name "*.sh"
Команда find
может применить любую команду к каждому найденному файлу. Например, вывести размер всех найденных файлов можно командой:
find ./ -name "*.sh" -exec stat -c "%s %n" {} \;
Для поиска текста можно использовать команды grep
и egrep
.
grep -n "some text" -r ./folder
egrep -n "some text" -r ./folder
где опция -n
означает, что нужно напечатать номер строки, в которой нашелся заданный текст; опция -r
задает рекурсивный поиск.
Команда pgrep
позволяет найти процесс по шаблону имени. Например, найти все запущенные bash-интерпретаторы можно командой:
pgrep "bash" -a
Часто возникает такая ситуация: кто-то запустил программу, занимающую все ресурсы компьютера, и мы должны подождать, пока эта программа завершится, и потом запустить свой скрипт. Сделать это можно с помощью такого bash-скрипта:
while [[ $(pgrep -f some_program) ]]; do
sleep 200
done
./my_script.py data.csv
Данный скрипт каждые 200 секунд будет проверять, выполняется ли еще программа с именем some_program
. Если нет, то запустится команда ./my_script.py data.csv
Если у нас есть файл с несколькими столбцами, разделенными пробелом, и мы хотим выбрать 1-ый, 3-ий и 5-ый стобец, то мы можем выполнить:
cut -d" " -f1,3,5 data.csv
Чтобы отсортировать содержимое файла по определенному (например, по 3-ему) столбцу:
sort -k3 data.csv
sort -k3 data.csv --numeric-sort
sort -k3 data.csv --reverse
где опция --numeric-sort
означает сравнивать значения в столбце как числа (иначе значения будут сравниваться как строки). Я сталкивался с глюками при сортировке чисел, поэтому работу этой команды стоит проверять.
Комадна join
объединяет два файла также, как и соответствующая команда языка SQL. Оба файла должны быть отсортированны по полю, по которому мы хотим их объединить.
Объединить два несортированных файла (first_data.csv
и second_data.csv
) по 4-ому полю можно так:
sort -k4 first_data.csv > first_data_sorted.csv
sort -k4 second_data.csv > second_data_sorted.csv
join -j 4 first_data_sorted.csv second_data_sorted.csv
Или одной командой, используя выход команды sort
как файл:
join -j 4 <(sort -k4 first_data.csv) <(sort -k4 second_data.csv)
С помощью команды sed
удобно выполнять замены в файле. Заменяемые строки можно задавать регулярным выражением. Например, если в файле data.csv для разделения полей используется запятая, а мы хотим, чтобы поля разделялись точкой с запятой, то мы можем выполнить:
sed -e "s/,/;/g" data.csv > data_semicolon_separated.csv
С помощью команды awk
удобно делать простые преобразования на данными.
Например, подсчитать сумму чисел во 2-ом столбце файла data.csv, если столбцы разделены запятой, можно командой:
cat data.csv |awk 'BEGIN{FS = ","} {res=res+$2} END{print res;}'