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
donefunction 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.csvtar 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;}'