bash
Table of Contents
- 1. bash
- 1.1. Introductory
- 1.1.1. Games
- 1.1.2. Resumen
- 1.1.3. A Guide to the Terminal, Console, and Shell
- 1.1.4. jlevy/the-art-of-command-line: Master the command line, in one page (Multiple language)
- 1.1.5. What helps people get comfortable on the command line?
- 1.1.6. explainshell.com - match command-line arguments to their help text
- 1.1.7. Líneas de comandos
- 1.1.8. Tools to simplify the Command Line
- 1.2. Resources
- 1.2.1. GitHub - awesome-lists/awesome-bash: A curated list of delightful Bash scripts and resources.
- 1.2.2. GitHub - alebcay/awesome-shell: A curated list of awesome command-line frameworks, toolkits, guides and gizmos. Inspired by awesome-php.
- 1.2.3. https://github.com/LeCoupa/awesome-cheatsheets/blob/master/languages/bash.sh
- 1.2.4. https://linuxcommandlibrary.com/
- 1.2.5. GitHub - dylanaraps/pure-bash-bible: 📖 A collection of pure bash alternatives to external processes.
- 1.2.6. dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external processes.
- 1.2.7. Links
- 1.2.8. Optimizing Linux Pipes | Hackaday
- 1.2.9. Shell startup scripts — flowblok’s blog
- 1.2.10. https://wizardzines.com/zines/bite-size-command-line/
- 1.2.11. https://wizardzines.com/zines/bite-size-bash/
- 1.2.12. Differences between set env export
- 1.3. Trucos
-
- 1.3.0.1. adduser sencillo, no interactivo
- 1.3.0.2. Crear un directorio si no existe
- 1.3.0.3. Argumentos de línea de comandos con getopts
- 1.3.0.4. Sacar información de un ordenador
- 1.3.0.5. Resolver una lista de hostnames
- 1.3.0.6. Procesar el resultado de un comando y sacarlo en tiempo real (streaming)
- 1.3.1. Encontrar qué paquete se corresponde con un comando
- 1.3.2. Sin clasificar
- 1.3.3. Progreso al copiar
- 1.3.4. Lista de un directorio a org-mode
- 1.3.5. Errores de certificados
- 1.3.6. Sacar el número de columnas de un csv
- 1.3.7. Sacar el nombre del ordenador
- 1.3.8. Y/n Prompt bash
- 1.3.9. Sacar número de líneas máximo para configurar el formateo
- 1.3.10. Renombrar con un nombre aleatorio
- 1.3.11. Generar 20 strings aleatorias de longitud 30
- 1.3.12. Sacar tamaño de imágenes
-
- 1.4. herramientas
- 1.5. Resumen
- 1.5.1. Atajos de teclado
- 1.5.2. Procesos
- 1.5.3. [[]]
- 1.5.4. (( ))
- 1.5.5. Todos los tipos [({})]
- 1.5.6. Aritmética de coma flotante
- 1.5.7. Shell Parameter Expansion / Substitution
- 1.5.8. arrays, variables ${var#pattern}
- 1.5.9. variables especiales $@, $?, IFS, PS1
- 1.5.10. Redirecciones, stdout, stderr
- 1.5.11. UI
- 1.6. Variables de entorno específicas a servicios de systemd
- 1.7. Syntax Tree
- 1.7.1. tbsp - tree-based source-processing language (treesitter awk)
- 1.7.2. https://github.com/ast-grep/ast-grep ast-grep(sg) is a CLI tool for code structural search, lint, and rewriting.
- 1.7.3. GitHub - getgrit/gritql: GritQL is a query language for searching, linting, and modifying code.
- 1.7.4. tree_sitter_graph::reference - Rust
- 1.7.5. * GitHub - semgrep/semgrep: Lightweight static analysis for many languages. Find bug variants with patterns that look like source code.
- 1.8. Alternative shell pipeline tools
- 1.8.1. jq
- 1.8.2. rq
- 1.8.3. hq - like jq, but for HTML
- 1.8.4. jc: converts the output of popular tools to JSON
- 1.8.5. dsq: run sql queries against JSON, CSV, Excel, Parquet, …
- 1.8.6. sq | wrangle data
- 1.8.7. https://github.com/prql/prql
- 1.8.8. jqnatividad/qsv: CSVs sliced, diced & analyzed. (Based on Rust+Polars)
- 1.8.9. dbohdan/structured-text-tools: A list of command line tools for manipulating structured text data
- 1.8.10. fx: Terminal JSON viewer & processor
- 1.8.11. Miller
- 1.8.12. Tools for editing/visualizing binary data?
- 1.8.13. Array Programming Languages
- 1.8.14. visidata
- 1.8.15. JMESPath — JMESPath
- 1.8.16. GitHub - tomnomnom/gron: Make JSON greppable!
- 1.9. Es bash un “lenguaje de programación serio”?
- 1.9.1. Programación más seria en bash (unofficial bash strict mode)
- 1.9.2. GitHub - bats-core/bats-core: Bash Automated Testing System
- 1.9.3. In defense of bash scripts - Bash is SUPER
- 1.9.4. https://cuddly-octo-palm-tree.com/posts/2021-10-31-better-bash-functions/
- 1.9.5. bash trap exception handling
- 1.9.6. Next Generation Shells (concept)
- 1.9.6.1. NGS (Language)
- 1.9.6.1.1. https://ngs-lang.org/doc/latest/man/ngslang.1.html → Language Principles
- 1.9.6.1.2. Why Next Generation Shell? – Ilya’s blog process
- 1.9.6.1.3. bash or Python? The Square Pegs and a Round Hole Situation – Ilya’s blog process
- 1.9.6.1.4. Why I have no favorite programming language – Ilya’s blog process
- 1.9.6.1.5. The Pseudo Narrow Waist in Unix – Ilya’s blog process
- 1.9.6.2. Oil Shell - Why Create a New Unix Shell? (2021)
- 1.9.6.3. Alternative Shells · oilshell/oil Wiki
- 1.9.6.4. Internal DSLs for Shell · oilshell/oil Wiki
- 1.9.6.5. Unique Semantics - Elvish Shell
- 1.9.6.6. Introduction | Nushell
- 1.9.6.7. Comparison of NGS, osh (oilshell), elvish shell, nushell
- 1.9.6.8. Charm: We build tools to make the command line glamorous
- 1.9.6.9. GitHub - Ph0enixKM/Amber: 💎 Amber the programming language compiled to bash
- 1.9.6.1. NGS (Language)
- 1.9.7. BASH with Debugger and Improved Debug Support and Error Handling
- 1.9.8. letam/shbang: Application Server Orchestration Library, based on Bash shell scripts 😬
- 1.9.9. Bringing the Unix Philosophy to the 21st Century - Brazil’s Blog
- 1.9.10. Please stop writing shell scripts
- 1.9.11. Shell utils
- 1.9.12. google/zx: A tool for writing better scripts Node.js + Bash
- 1.10. (Rust) replacements for gnu utils
- 1.1. Introductory
1. bash
1.1. Introductory
1.1.1. Games
1.1.1.1. https://cmdchallenge.com
1.1.1.2. TICKLER Codédex | Start your coding adventure! track
Command line version cooming soon…
1.1.2. Resumen
Explicar más las convenciones que hay y lo que te ofrece una terminal (affordances)
Barras /
Path relativo absoluto
Flags ls -l, –help -h
Poner o no / al final del directorio, poner o no poner el nombre del archivo cuando copias, directorio actual, cd
cp, mv, cd, ls
chmod, chown
nano
fg, bg cuando haces C-z con nano
- Atajos de teclado
C-c → cortar proceso y limpiar comando actual
Tab → autocompletar todo
C-r → buscar historial
C-d → salir de la terminal
1.1.3.
1.1.4. jlevy/the-art-of-command-line: Master the command line, in one page (Multiple language)
1.1.7. Líneas de comandos
1.1.8. Tools to simplify the Command Line
1.2. Resources
1.2.1. GitHub - awesome-lists/awesome-bash: A curated list of delightful Bash scripts and resources.
1.2.5. GitHub - dylanaraps/pure-bash-bible: 📖 A collection of pure bash alternatives to external processes.
1.2.6. dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external processes.
1.2.7. Links
- https://tldp.org/LDP/abs/html/ → documentación estándar
- tldr man pages with practical examples.
- https://devhints.io/bash
- How are Unix pipes implemented? incluye links a código muy antiguo (hasta 1970) de UNIX
1.2.8. Optimizing Linux Pipes | Hackaday
1.2.8.1. Linux Fu: Simple Pipes | Hackaday
1.2.8.2. Linux Fu: Pimp Your Pipes | Hackaday
1.2.8.4. How fast are Linux pipes anyway?
1.2.9. Shell startup scripts — flowblok’s blog
.bashrc .profile diagram
1.2.12. Differences between set env export
1.3. Trucos
stty sane
→ cuando te peta la terminal y no puedes escribirsetxkbmap es
,setxkbmap us
→ Para poner el teclado en español / en inglés americanoxkill
→ kill seleccionando gráficamente la ventanasudo timedatectl set-timezone "Europe/Madrid"
→ Zona horaria de Madrid- Sacar tu IP pública
dig +short myip.opendns.com @resolver1.opendns.com
,curl ifconfig.co
- Cambiar fecha de modificación de un archivo
touch -d "30 days ago"
1.3.0.1. adduser sencillo, no interactivo
adduser --disabled-password --gecos "" <username>
1.3.0.2. Crear un directorio si no existe
[ -d foo ] || mkdir foo
1.3.0.3. Argumentos de línea de comandos con getopts
curl cheat.sh/bash+getopts2 # question_id: 402377 # `getopt` and `getopts` are different beasts, and people seem to have a # bit of misunderstanding of what they do. `getopts` is a built-in # command to `bash` to process command-line options in a loop and assign # each found option and value in turn to built-in variables, so you can # further process them. `getopt`, however, is an external utility # program, and it _doesn't actually process your options for you_ the # way that e.g. bash `getopts`, the Perl `Getopt` module or the Python # `optparse`/`argparse` modules do. All that `getopt` does is # canonicalize the options that are passed in — i.e. convert them to a # more standard form, so that it's easier for a shell script to process # them. For example, an application of `getopt` might convert the # following: myscript -ab infile.txt -ooutfile.txt # into this: myscript -a -b -o outfile.txt infile.txt # You have to do the actual processing yourself. You don't have to use # `getopt` at all if you make various restrictions on the way you can # specify options: #
- only put one option per argument;
- all options go before any positional parameters (i.e. non-option arguments);
- for options with values (e.g. `-o` above), the value has to go as a separate argument (after a space).
https://unix.stackexchange.com/questions/182285/calling-bash-getopts-from-a-function-fails-the-2nd-time
The answer is that getopts keeps the pointer in $OPTIND and therefore the trick is to add local OPTIND or OPTIND=1 to the beginning of the getopt_test function.
OPTIND=1
1.3.0.3.1. http://abhipandey.com/2016/03/getopt-vs-getopts/
Generally, try to stay away from getopt for the following reasons:
- External utility
- Traditional versions can’t handle empty argument strings, or arguments with embedded whitespace
- For the loops to work perfectly, you must provide the values in the same sequence as the for loop itself; which is very hard to control
- Mostly a way to standardize the parameters
1.3.0.4. Sacar información de un ordenador
separator="=============================================" archivo=dump.txt echo $separator >> $archivo 2>&1 cat /proc/cpuinfo >> $archivo 2>&1 echo $separator >> $archivo 2>&1 cat /proc/meminfo >> $archivo 2>&1 echo $separator >> $archivo 2>&1 lspci >> $archivo 2>&1 echo $separator >> $archivo 2>&1 cat /proc/bus/pci/devices >> $archivo 2>&1 echo $separator >> $archivo 2>&1 lsblk >> $archivo 2>&1 echo $separator >> $archivo 2>&1 cat /proc/partitions >> $archivo 2>&1 echo $separator >> $archivo 2>&1 ( sudo dmidecode || dmidecode ) >> $archivo 2>&1 echo $separator >> $archivo 2>&1 ( sudo cat /sys/devices/virtual/dmi/id/* || cat /sys/devices/virtual/dmi/id/* ) >> $archivo 2>&1 echo $separator >> $archivo 2>&1
1.3.0.5. Resolver una lista de hostnames
cat hostnames.txt | sed -E "s%https?://%%;s%/.+%%" | xargs -I _ host _ | grep -E 'has (IPv6 )?address'
1.3.0.6. Procesar el resultado de un comando y sacarlo en tiempo real (streaming)
result=$(command | tee /dev/tty)
1.3.1. Encontrar qué paquete se corresponde con un comando
1.3.2. Sin clasificar
- nl para añadir números de línea
echo -e "one\ntwo\nthree" | nl
- flock para crear locks en scripts de bash
- https://www.shellcheck.net/ → finds bugs in your shell scripts (linting)
Ctrl+R para buscar hacia delante comandos
stty stop ^P # Ponerlo en ~/.bashrc para que Ctrl+S sirva para buscar hacia delante (Ctrl+R hacia atrás)
1.3.3. Progreso al copiar
1.3.3.1. Sacar el progreso
Para zsh
src="/media/extract2"; dst="/media/julian/DVD/extract2"; while true; do echo $(( ($(du -d 1 $dst | tail -n 1 | awk '{print $1}') * 100.0) / $(du -d 1 $src | tail -n 1 | awk '{print $1}') )); sleep 5; done
Para bash
src="~/Documents"; dst="/media/pi/Linux Backup/linux/Documents"; while true; do echo $(( ( $(du -d 1 "$dst" | tail -n 1 | awk '{print $1}') * 100) / $(du -d 1 "$src" | tail -n 1 | awk '{print $1}') )); sleep 5; done
1.3.3.2. progreso al copiar un disco entero
while (true); do echo "scale=4; $(df /dev/dm-3 | tail -n 1 | awk '{print $3}')*100.0/469969564.0" | bc; sleep 5; clear; done # Donde 469969564.0 es el tamaño en bloques usados del dispositivo de la copia
Disclaimer: como es un método un poco chapucero, es posible que se quede
por debajo o por encima del 100% en algunos casos
1.3.3.3. progreso al copiar de una carpeta a otra
Funciona mejor en zsh, con más decimales
src=""; dst=""; while true; do echo $(( ($(du -d 1 $dst | tail -n 1 | awk '{print $1}') * 100.0) / $(du -d 1 $src | tail -n 1 | awk '{print $1}') )); sleep 5; done
1.3.4. Lista de un directorio a org-mode
Tienes que recorrer el árbol en preorder
https://stackoverflow.com/questions/76169133/how-do-i-do-a-pre-order-file-traversal-in-bash
findfile_preorder()( shopt -s dotglob nullglob for p; do printf '%s\n' "$p" [[ ! -L $p && -d $p ]] && findfile_preorder "$p"/* done ) findfile_preorder Documents | awk -F/ '{for (i=1; i<NF; i++) printf("*"); print " " $0}' findfile_preorder Documents | awk -F/ '{for (i=1; i<NF; i++) printf("*"); print " " $0}' | sed -E 's/^\*+ (.+)/echo -e "&\\n:PROPERTIES:\\n:ID: $(uuidgen --sha1 --namespace @url --name \\\"\1\\\")\\n:END:\\n\1"/' | bash
1.3.5. Errores de certificados
sudo chmod 755 /etc /etc/ssl /etc/ssl/certs sudo chmod 644 /etc/ssl/certs/ca-certificates.crt
1.3.6. Sacar el número de columnas de un csv
- Si el número de columnas varía dentro de un mismo csv
grep "GPS" trackLog-2021-nov.-01_17-48-32.csv | grep -n -o "," | sort -n | uniq -c | cut -d : -f 1 # GPS es el nombre de una columna que sabes que va a existir siempre
1.3.7. Sacar el nombre del ordenador
https://unix.stackexchange.com/questions/574808/get-the-hardware-model-name-in-linux
if [[ -d /system/app/ && -d /system/priv-app ]]; then model="$(getprop ro.product.brand) $(getprop ro.product.model)" elif [[ -f /sys/devices/virtual/dmi/id/product_name || -f /sys/devices/virtual/dmi/id/product_version ]]; then model=$(< /sys/devices/virtual/dmi/id/product_name) model+=" $(< /sys/devices/virtual/dmi/id/product_version)" elif [[ -f /sys/firmware/devicetree/base/model ]]; then model=$(< /sys/firmware/devicetree/base/model) elif [[ -f /tmp/sysinfo/model ]]; then model=$(< /tmp/sysinfo/model) fi echo $model
HP ZBook Firefly 15 G7 Mobile Workstation
1.3.8. Y/n Prompt bash
read -p "Continue? [Y/n] " yn case $yn in [yY]) true ;; [nN]) exit ;; * ) true ;; esac
1.3.9. Sacar número de líneas máximo para configurar el formateo
find . -iname "*.py" | xargs -I % wc -L "%" | sort -nr | head -n 20
1.3.10. Renombrar con un nombre aleatorio
for f in *.jpg; do random_string=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 1); nuevo_nombre="${random_string}.jpg" mv "./$f" "$nuevo_nombre" done
1.3.11. Generar 20 strings aleatorias de longitud 30
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 20
1.3.12. Sacar tamaño de imágenes
find . -iname '*.jpg' | xargs -I _ bash -c "echo -en \"_\t\t\t\"; exiftool _ | grep 'Image Size' | awk '{print \$4}'" | sort
1.4. herramientas
1.4.1. misc
- agrep Fuzzy grep
sort, unique, head, tail
- Regex con sed y con grep siempre usar -E (extended) para que haga cosas normales y esperables y no tener que poner 4 backslashes
seq start step end
wc
wordcount para contar líneas, caracteres, …tee
se usa mucho pero ni idea cómo va
Por ejemplo si haces result=$(command | tee /dev/tty) puedes tener a la vez el resultado del comando y la salida en tiemo realtac
es como cat sèver la orep
1.4.2. grep
- grep recursivo
grep -r --include "*.txt" regex .
1.4.2.1. Colores con (rip)grep y less
https://linuxcommando.blogspot.com/2007/10/grep-with-color-output.html
grep --color=always abc a_file.txt | less -R rg -p | less -R
1.4.3. sed
- https://unix.stackexchange.com/questions/26284/how-can-i-use-sed-to-replace-a-multi-line-string
- Ranges with search
sed '/red,/blue/s/are/be'
Replace from first match of expr to next match of that expr - Brace expansion
sed -n '2,3 {s/are/be; p}'
- Multiple commands:
sed -e 'script1' -e 'script2'
sed 'script1;script2'
sed '<RET>
→ multiline input in shell
- Multiline match:
-z
→ null character as end of line, similar to multiline mode -n
→ suppress print by default every line (useful when you want to print specific lines)- Using sed to insert lines before or after a match – Fabian Lee : Software Engineer
- https://www.thegeekstuff.com/2009/12/unix-sed-tutorial-7-examples-for-sed-hold-and-pattern-buffer-operations/
sed -n '1!G;h;$p'
hace lo mismo quetac
1.4.4. find
find ~+
para que te saque el path completo
1.4.4.1. Eliminar archivos por extensión
list=`find . -name *.pyc` readarray -t goodlist <<<"$list" for ((i=0; i<= ${#goodlist}; i++)); do rm "${goodlist[i]}"; done
1.4.4.2. Ejecutar cosas contra los matches find
find -iname "*sync-conflict*" -exec sh -c 'rm {}' \;
1.4.4.3. hash de una carpeta (determinista)
Si no le pones el LC_ALL=C te depende del locale en el que lo ejecutes
find /path/to/folder/ -type f -print0 | LC_ALL=C sort -z | xargs -0 sha1sum | sha1sum # Para comprobar que es igual a un hash [[ $(find . -type f -not -name '*csv' -print0 | LC_ALL=C sort -z | xargs -0 sha1sum | sha1sum) = "009d6a0a9544379f70e365ea904c9835905cee89 -" ]] # Si sólamente te interesa comparar si dos carpetas son iguales, pongamos tfrecord1 y tfrecord2: find tfrecord1 -type f -print0 | LC_ALL=C sort -z | xargs -0 sha1sum | awk '{print $1}' | sha1sum find tfrecord2 -type f -print0 | LC_ALL=C sort -z | xargs -0 sha1sum | awk '{print $1}' | sha1sum
Faltaría hacerlo genérico
1.4.4.4. Operadores booleanos (or de varias condiciones)
Por defecto te los une con un and
find Documents \( -iname "*pdf" -o -iname "*.epub" \)
https://man7.org/linux/man-pages/man1/find.1.html → OPERATORS
1.4.4.5. Permisos recursivos de una carpeta
find folder/ -type f -exec bash -c "chmod 644 \"{}\"" \; chmod 664 -R folder/ # Suele ser más rápido que lo anterior find orgzly/ -type d -exec bash -c "chmod 755 \"{}\"" \; # Para poder acceder a los directorios
1.4.5. awk
Use cut when possible instead of awk
cat /etc/passwd | cut -d ':' --output-delimiter=" " -f 1,5-7
https://github.com/FreedomBen/awk-hack-the-planet → excellent awk resource, github repo + videos
-F
→ set Field Separator
$NF # Último campo $(NF-n) # Campo n empezando por la izquierda FS # (Input) Field Separator OFS # Output Field Separator awk 'BEGIN{FS=":"; OFS=","} {print $0}' /etc/passwd # Change field separator from : to ; awk "/pattern/ action" Se pueden sumar columnas numéricas length($0) → Longitud de la línea, se puede utilizar como una condición length($0) < 8 { if ($NF == "/bin/bash") print $0 } Multiple conditions with && df -a 2>/dev/null | awk '{ if ($0 ~ /\/dev\/loop/ && length($1) < 11) print $1"\t"$2+$3}' match($0, /o/) → Matches entries with "o" awk 'NR==7 NR==11, {print NR, $0}' # Print from 7 through 11, printing also line number NF → Number of Fields, NR → Number of Records Pasar variables de entorno a awk con -v avar="$var", luego la puedes utilizar como avar (sin $) en awk
1.4.5.1. Print last N columns
https://stackoverflow.com/questions/2961635/using-awk-to-print-all-columns-from-the-nth-to-the-last
awk '{$1=$2=""; print $0}' somefile
https://bytefreaks.net/gnulinux/bash/use-awk-to-print-the-last-n-columns-of-a-file-or-a-pipe
awk '{n = 2; for (--n; n >= 0; n--){ printf "%s\t",$(NF-n)} print ""}';
1.4.6. less
less -N # para que tenga numero de linea less -R # para que interprete las secuencias de escape de colores
1.4.7. tail
tail -F <archivo> # Sigue al archivo según se añaden cosas, con --retry si se corta tail -s <n> -f <log> # follows the log refreshing each n seconds
1.4.8. Pequeñas y efectivas
- inotify para disparar acciones en función de cambios en el sistema
- notify-send para lanzar notificaciones en escritorio
- dunst es un pelín más sofisticado y te permite poner botones que lanzan acciones
- dunst es un pelín más sofisticado y te permite poner botones que lanzan acciones
- tmux para lanzar procesos y comprobar cómo van, hacer splits en la propia terminal
- termux puede hacer de todo en android (menús, notificaciones, escanear nfcs…)
- pv para que pinte el progreso (también vale tqdm)
1.4.9. fzf
1.4.10. pipes en paralelo (DAGs)
Las partes secuenciales se expresan bien con operadores tipo pipe (|)
https://github.com/flonatel/pipexec
https://news.ycombinator.com/item?id=39656056
https://www2.dmst.aueb.gr/dds/sw/dgsh/
Tenía un ejemplo de parallel pero no sé si es este
now="$(date +'%Y-%m-%d %H:%M:%S')" echo "file|link|status" > "link_rot $now.csv" rg -H "https?://" \ | sed -E 's%(.+\.org)\:.+?(https?://[^] ]+).+?%\1|\2%g' \ | parallel --colsep '\|' curl -o /dev/null -s -w '{1}\|{2}\|%{http_code}\\n' '{2}' \ | tee -a "link_rot $now.csv"
1.4.11. curl
trace-ascii para ver todos los pasos que hace curl
curl --trace-ascii curl.trace
1.5. Resumen
1.5.1. Atajos de teclado
stty --all
Ctrl+C → Stop Current Comand (SIGINT) Ctrl+D → End of input (exit shell) Ctrl+\ → SIGQUIT, mas estricto que SIGINT Ctrl+Z → SIGTSTP, detiene el proceso Ctrl+S → Halt output to screen Ctrl+Q → Restart output to screen Ctrl+J → New line Ctrl+L → Clear Esc+Enter → New line without executing command
https://ss64.com/bash/syntax-keyboard.html
Autocompletado
TAB → General Esc+? → Todas las posibilidades Esc+/ → Archivo Ctrl+X/ → Todos los archivos Esc+~ → Usuario Ctrl+X~ → Todos los usuarios Esc+$ → Variable Ctrl+X$ → Todas las variables Esc+@ → Host Ctrl_X@ → Todos los hosts
1.5.2. Procesos
$ <comando>
→Ctrl+Z
lo detiene →$ bg
lo ejecuta en segundo
plano,$ fg
lo ejecuta en primer planocomando &
→ correr en segundo plano
1.5.2.1. double forking
(setsid command &)
- This uses ( &) to fork to background
- setsid to detach from the controlling tty.
1.5.2.2. Ejecutar un proceso redirigiendo logs
export MY_VAR="foobar"; run_my_command > "log_`date -Iseconds`.txt" 2>&1
1.5.3. [[]]
- Diferencia entre
[[
(CONDITIONAL EXPRESSIONS) y[
, operadores
numéricos y strings - Utilizar
[ ]
cuando quieres testear si una expresión devuelve algo o no,[ -z ]
cuando es lo contrario - https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
- https://unix.stackexchange.com/a/306115
- https://stackoverflow.com/questions/3869072/test-for-non-zero-length-string-in-bash-n-var-or-var
This is a more complete version that shows more differences between[
(akatest
) and[[
1.5.4. (( ))
- Aritmética de enteros
- En zsh también tiene aritmética de coma flotante
1.5.5. Todos los tipos [({})]
1.5.6. Aritmética de coma flotante
bc <<< 'scale=2; 100/3' echo "scale=2; 100/3" | bc
1.5.7. Shell Parameter Expansion / Substitution
https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion
https://tldp.org/LDP/abs/html/parameter-substitution.html
https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash
if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi
if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi
1.5.8. arrays, variables ${var#pattern}
1.5.8.1. Extensiones de archivos
full_path="/var/log/Xorg.0.log.old" filename=${full_path##*/} full_extension=${filename#*.} extension=${filename##*.}
1.5.8.2. Todas las separaciones posibles
var=first:middle:last ${var##*:} → last ${var#*:} → middle:last ${var%%:*} → first ${var%:*} → first:middle var=one:two ${var##*:}, ${var#*:} → two ${var%%:*}, ${var%:*} → one var=only todas dan simplemente only
1.5.8.3. Arrays asociativos
Depende de zsh o bash
declare -A array for dir in ~/.local/share/venvs/*; do if echo $dir | grep -v -e shims -e versions 1>/dev/null; then; array["$dir"]=$(readlink $dir/project); fi; done echo ${array["/home/julian/.local/share/venvs/133063051db23bd4a339770311f9c270"]}
/home/julian/code/conv
arr=my_array declare -A "$arr" declare "$arr[foo]=bar" echo "${my_array[foo]}" bar
This provides the indirection you need. The argument $arr[foo]=bar
is expanded to my_array[foo]=bar
, which is a valid assignment expression to be processed by declare
.
1.5.9. variables especiales $@, $?, IFS, PS1
1.5.10. Redirecciones, stdout, stderr
- https://unix.stackexchange.com/questions/37660/order-of-redirections
- https://catonmat.net/ftp/bash-redirections-cheat-sheet.pdf
Redireccionar
El 2>&1 va después
command >> /path/to/log 2>&1
1.5.10.1. Illustrated Redirection Tutorial [Bash Hackers Wiki]
1.5.11. UI
- whiptail
- feedgnuplot Plots por línea de comandos (empipable)
1.6. Variables de entorno específicas a servicios de systemd
https://youtu.be/9kFE5WVL5O0
Variables de entorno especificas a servicios de systemd
Utilizar cuando pase a un servicio las cosas de orgzly-integrations
1.7. Syntax Tree
1.7.1. tbsp - tree-based source-processing language (treesitter awk)
tbsp is an awk-like language that operates on tree-sitter syntax trees.
1.7.2. https://github.com/ast-grep/ast-grep ast-grep(sg) is a CLI tool for code structural search, lint, and rewriting.
1.8. Alternative shell pipeline tools
Tools that work with an alternative to the UNIX text stream (JSON, CSV, HTML)
1.8.1. jq
1.8.1.1. Awesome jq
1.8.1.2. jq Manual (development version)
1.8.1.3. jq Cheat Sheet
https://gist.github.com/olih/f7437fb6962fb3ee9fe95bda8d2c8fa4
JSON -> [{"text": ...}, {"text": ...}, {"text": ...}] jq_schema -> ".[].text" JSON -> {"key": [{"text": ...}, {"text": ...}, {"text": ...}]} jq_schema -> ".key[].text" JSON -> ["...", "...", "..."] jq_schema -> ".[]"
1.8.1.5. jj: faster jq
1.8.1.6. trucos jq
Streaming agrupando entradas
(echo 1 2 3; sleep 2; echo 4 5 6) | jq --stream '[., input, input] | flatten'
1.8.2. rq
https://github.com/dflemstr/rq
The goal is to make ad-hoc exploration of data sets easy without having to use more heavy-weight tools like SQL/MapReduce/custom programs. rq fills a similar niche as tools like awk or sed, but works with structured (record) data instead of text. It is similar to jq, but supports more record formats and has a far more advanced query engine.
1.8.3. hq - like jq, but for HTML
1.8.4. jc: converts the output of popular tools to JSON
1.8.5. dsq: run sql queries against JSON, CSV, Excel, Parquet, …
1.8.6. sq | wrangle data
1.8.7. https://github.com/prql/prql
1.8.8. jqnatividad/qsv: CSVs sliced, diced & analyzed. (Based on Rust+Polars)
1.8.9. dbohdan/structured-text-tools: A list of command line tools for manipulating structured text data
1.8.10. fx: Terminal JSON viewer & processor
1.8.11. Miller
https://github.com/johnkerl/miller
Miller is like awk, sed, cut, join, and sort for data formats such as CSV, TSV, JSON, JSON Lines, and positionally-indexed.
1.8.12. Tools for editing/visualizing binary data?
binary formats could also have viewers and editors. Those destined for human creation and consumption generally are, but data exchange formats rarely have the same love, and as such stay unreadable. They don’t have to be. They can be drawn on the screen or even directly edited. We just need to write the tools.
1.8.13. Array Programming Languages
1.8.14. visidata
1.8.15. JMESPath — JMESPath
1.8.16. GitHub - tomnomnom/gron: Make JSON greppable!
gron transforms JSON into discrete assignments to make it easier to grep
for what you want and see the absolute ’path’ to it.
1.9. Es bash un “lenguaje de programación serio”?
1.9.1. Programación más seria en bash (unofficial bash strict mode)
http://redsymbol.net/articles/unofficial-bash-strict-mode/
https://stackoverflow.com/questions/685435/trace-of-executed-programs-called-by-a-bash-script
https://linoxide.com/change-bash-prompt-variable-ps1/
# Para que al dar error salga del script y no siga ejecutando cosas a lo loco, igual que haría cualquier lenguaje de programación decente: set -e # Variables no definidas lanzan un error: set -u # Hacer que las pipes devuelvan el estado del comando set -o pipefail true | false | true # Esto devuelve 0 sin pipefail (coge el true de la derecha) y 1 con pipefail (coge el false de en medio) IFS=$'\n\t' # No separa por espacios Todo junto: #+begin_src bash #!/bin/bash set -euo pipefail IFS=$'\n\t'
1.9.1.1. Debugging en bash
# DEBUGGING # Para debugear, imprime lo que se está ejecutando en cada momento y su número de línea # !Importante! Poner ', nunca " (con " se evalúa en el momento, y $LINENO devuelve la línea en la que defines PS4) # !Importante! No poner comandos en PS4 porque si no se ejecutan infinitamente (Un print de PS4 necesita evaluar un comando, que genera otro print de PS4, que evalua el comando otra vez, ...) # Versión con menos cosas, para scripts individuales que no llaman a funciones ni a otros archivos # EPOCHREALTIME funciona desde bash 5, si no no se imprime nada PS4='+[\D{%d-%m-%y %H:%M:%S}${EPOCHREALTIME##*.}] ${LINENO}:' # Versión completa PS4='+[\D{%d-%m-%y %H:%M:%S}${EPOCHREALTIME##*.}] ${FUNCNAME[0]}() $BASH_SOURCE:${BASH_LINENO[0]}: ' set -x # Imprime lo de arriba cada vez que se ejecuta algo # Tracebacks en bash function traceback() { i=0; while caller $i ;do printf "%$i""s"; ((i++)) ;done }
1.9.1.2. Ejecutar línea por línea un script
https://stackoverflow.com/questions/9080431/how-execute-bash-script-line-by-line
set -x trap read debug
1.9.1.3. Poner excepciones de verdad en bash?
Lo mismo se puede combinar de alguna manera un PS4 chulo con set -x y lanzarlo sólamente en un trap, aunque creo que en ese caso sólamente tienes la última excepción
Funciona mejor con callee
1.9.2. GitHub - bats-core/bats-core: Bash Automated Testing System
1.9.2.1. Rewriting Bash scripts in Go using black box testing - Stack Overflow Blog
1.9.3. In defense of bash scripts - Bash is SUPER
- Simple
When describing shell scripts as simple (not “simple to use”nk ), I mean that there are virtually no dependencies needed in order to run a simple bash script - Ubiquitous
- Portable
You really can’t get more portable than shell scripts. There’s no need to install text editors or update packages or install dependencies - Efficient
e.g.: https://adamdrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html - Robust
Piping functions is robusts. Since monads are like pipes, and a monad is just a monoid in the category of endofunctors, it follows that bash scripting, when done well, is like functional programming
1.9.3.1. Friends don’t let friends program in shell script
Why?
- Shell script is ugly.
- Shell script is unreliable.
- Shell script doesn’t have exceptions.
- Shell script is hard to debug.
- Shell script is hard to test.
- Shell script isn’t object oriented.
- Shell script is full of idiosyncratic cruft.
- Shell script doesn’t have any decent data structures.
- Shell script doesn’t scale.
- Shell script encourages code duplication.
1.9.4. https://cuddly-octo-palm-tree.com/posts/2021-10-31-better-bash-functions/
- Use
()
instead of{}
to use lexical scope instead of dynamic scope (lexical scope means callee functions cannot access variables created in the scope of the caller function, unlike dynamic scope) - Use traps for safe cleanup
1.9.5. bash trap exception handling
1.9.6. Next Generation Shells (concept)
1.9.6.1. NGS (Language)
https://ngs-lang.org/
NGS: next generation shell para sustituir bash, habla de carencias de bash
- shell pipes do feel ergonomic but conceptually unidirectional untyped byte streams are not that impressive these days.
- The “problem” with general-purpose languages is that they don’t have ergonomic facilities for DevOps.
run an external process, get the exit code of the external process, work with files - The “problem” with bash:
extremely poor error handling, missing data structures, syntax.
A related observation is that other languages also had afterthoughts such as “use strict” which very roughly corresponds toset -eu
in bash. - NGS design
https://console.substack.com/p/console-92?s=r
- Small scripts don’t pay / Small scripts stay small
- You don’t need to pay for something that is possible in the language when you don’t use it.
Example: main() function. It provides a very ergonomic way to parse the command line arguments. When you don’t care about arguments - just don’t define main(), the script runs top to bottom. - Syntax compression
- The more frequently used a feature is, the shorter the syntax will be.
- Small number of concepts
- For example, NGS does not have classes. There are types and methods.
- Features
exceptions, types with inheritance, multiple dispatch, guards (additional conditions to invoke a method), basic functional programming support, patterns, (new, in progress) facility for deeply nested data manipulation, automatic parsing of command line arguments when invoking the optional main(), threads, domain-specific syntax and facilities for running external programs and file manipulation. - Further NGS design
https://ngs-lang.org/doc/latest/man/ngslang.1.html
1.9.6.1.1. https://ngs-lang.org/doc/latest/man/ngslang.1.html → Language Principles
- Systems engineers’ language
NGS is a domain-specific language. It is aimed to solve common system tasks in a convenient manner «more structured text than bash, namely json» - Uniformity
NGS tries to be uniform wherever possible to minimize surprises. The idea here is to match between expected and actual behaviour of given method plus parameters. - Power
As a rule, trade-offs between power and not allowing to shoot yourself in the foot are resolved in favor of the power solution. The language is aimed at experienced engineers which use their own judgement. The language should be powerful enough to shoot all feet in the building at once. - Simple methods naming for less guess work
For example, the multimethod+
:
1 + 2
adds the numbersarr1 + arr2
adds (concatenates) arrayshash1 + hash2
produces merged hash.
- Extensibility
fetch('your_file.super-format')
can be extended to decode your format.read
, which reads from a file, can be extended to support HTTP or S3.- Most of the syntax (for example
my_var.my_field
ormy_var[my_index]
) is just sugar for calling methods. This behaviour lets you, the user, define any operator for existing or your custom types.
- Simplicity
Very small number of core concepts in the language:
- Types with a simple type system, geared only toward multiple dispatch. No classes.
- Multimethods, which allow using same method name for operations on different types, as in the
+
example above. - Closures
- Exceptions
- Types with a simple type system, geared only toward multiple dispatch. No classes.
- Familiarity
Many concepts and syntax constructs come from other languages.
1.9.6.1.2. Why Next Generation Shell? – Ilya’s blog process
1.9.6.1.3. bash or Python? The Square Pegs and a Round Hole Situation – Ilya’s blog process
1.9.6.1.4. Why I have no favorite programming language – Ilya’s blog process
1.9.6.1.5. The Pseudo Narrow Waist in Unix – Ilya’s blog process
Contrast with A Kardashev scale for interfaces - by Gordon Brander
1.9.6.2. Oil Shell - Why Create a New Unix Shell? (2021)
- Shouldn’t we discourage people from writing shell scripts?
- It won’t work. Like PHP, the shell language is useful, ubiquitous, flawed, and being improved.
- Even if a new line of shell never gets written, there will still be a huge installed base of shell scripts that you may need to understand (e.g. when they don’t work).
- Shell is still the best tool for many jobs. (cloud/devops)
- It won’t work. Like PHP, the shell language is useful, ubiquitous, flawed, and being improved.
1.9.6.2.1. Shell, Awk, and Make Should Be Combined
1.9.6.2.2. The Internet Was Designed With a Narrow Waist
Narrow waist facilitates interoperability
- Narrow Waist
The narrow waist (of an hourglass) is a software concept that solves an interoperability problem, avoiding an O(M × N) explosion. All of these are narrow waists:
- Interchange formats like JSON
- Networking protocols like HTTP
- Operating system interfaces like Win32 and POSIX
- Instruction set architectures like x86, and arguably WebAssembly.
- «Language Server Protocol, Debugger Adapter Protocol and Treesitter are also examples»
O(M × N) code explosion — A system may need bespoke code to fill in every cell of a grid, like M algorithms and N data structures, or M languages and N operating systems. This problem can often be mitigated by better software architecture, e.g. with protocols, interchange formats, or intermediate representations.
- Interchange formats like JSON
1.9.6.5. Unique Semantics - Elvish Shell
1.9.6.6. Introduction | Nushell
1.9.6.7. Comparison of NGS, osh (oilshell), elvish shell, nushell
- NGS
- small scripts don’t pay the price that bigger scripts may
- The more frequently used a feature is, the shorter the syntax will be.
- The more frequently used a feature is, the shorter the syntax will be.
- small scripts don’t pay the price that bigger scripts may
- oilshell
- backwards-compatible with bash
- backwards-compatible with bash
- elvish shell
- nushell
1.9.6.8. Charm: We build tools to make the command line glamorous
More like extending bash, specially with Bubble Tea
1.9.9. Bringing the Unix Philosophy to the 21st Century - Brazil’s Blog
https://blog.kellybrazil.com/2019/11/26/bringing-the-unix-philosophy-to-the-21st-century/
Estandarizar la salida de los programas en bash para que se puedan encadenar más fácilmente
1.9.10. Please stop writing shell scripts
1.9.10.1. The problem with shell scripts
- Errors don’t stop execution
- Unknown variables cause no errors
- Pipes don’t catch errors
- Subshells are weird
1.9.10.2. Some bad reasons to use shell scripts
- It’s always there!
If you’re packaging an app writen in X, use X with is shell convenience packages! - Just write correct code!
In practice:
- You’re probably not working alone; it’s unlikely everyone on your team has the relevant expertise.
- Everyone gets tired, gets distracted, and otherwise ends up making mistakes.
- Almost every complex shell script I’ve seen was lacking the
set -euo pipefail
invocation, and adding it after the fact is quite difficult (usually impossible). - I’m not sure I’ve ever seen an automated test for a shell script. I’m sure they exist, but they’re quite rare.
- You’re probably not working alone; it’s unlikely everyone on your team has the relevant expertise.
- Shellcheck will catch all these bugs!
Will catch some of the problems, but not all
1.9.10.3. Shell scripts are fine in some situations
- For one-off scripts that you are manually supervising, you can get away with laxer practices.
- Sometimes you really have no guarantees that another programming language is available, and you need to use the shell to get things going.
- For sufficiently simple cases, just running a few commands sequentially, with no subshells, conditional logic, or loops,
set -euo pipefail
is sufficient (and make sure you useshellcheck -o all
)
1.9.11. Shell utils
1.9.12. google/zx: A tool for writing better scripts Node.js + Bash
1.10. (Rust) replacements for gnu utils
1.10.1. Ver “Rust Programs Every Linux User Should Know About” en YouTube
https://youtu.be/dQa9mveTSV4
replacements for gnu utils
- ls with syntax highlight rwx
- cat with syntax highlight
- find but simpler
- ripgrep
- ps with syntax highlight
- faster cp