[2024-feb-29] Sad news: Eric Layton aka Nocturnal Slacker aka vtel57 passed away on Feb 26th, shortly after hospitalization. He was one of our Wiki's most prominent admins. He will be missed.

Welcome to the Slackware Documentation Project

¡Esta es una revisión vieja del documento!


En proceso de traducción. Victor

Construcciones de CLI e información útil

El propósito de este artículo no es ser un tutorial de CLI, sino más bien ser una exposición de construcciones comunes utilizadas en shell scripting para lograr un objetivo de manera eficiente. También hay secciones que simplemente ayudan a entender un tema determinado.

Construye

rev | cut | rev

A menudo es útil revertir una cadena y luego usar cut. Por ejemplo, tome un paquete Slackware y obtenga su nombre:

echo dejavu-fonts-ttf-2.33-noarch-1 | rev | cut -d - -f 1-3 --complement | rev
ls -1 /var/log/packages | rev | cut -d - -f 1-3 --complement | rev

O si desea obtener la ruta completa de un archivo, menos el sufijo.

echo /proc/config.gz | rev | cut -d. -f1 --complement | rev

Reemplazar un sufijo

Digamos que querías hacer un script de conversión de video y que necesitabas cambiar el sufijo.

input=test.mkv
output="$(basename "$input" .mkv).avi"

find | xargs

Esta es una interacción especial entre find y xargs que permite tratar espacios en los nombres de archivos. Es muy rápido porque muchos comandos como rm , rmdir y shred toman múltiples entradas de archivos en la línea de comandos. Una construcción genérica es algo como:

find . -type f -print0 | xargs -0 "$command"

Puede reemplazar $ command con cualquier comando que necesite para ejecutar en los archivos siempre que sea compatible con la entrada de múltiples archivos. Si tiene una lista de archivos, aún puede conservar espacios:

tr '\n' '\0' < "$file" | xargs -0 "$command"

comm antes y después

Esta construcción es útil para aplicaciones de gestión de paquetes. Desde la página de manual de comm:

With  no  options,  produce  three-column  output.
Column one contains lines unique to FILE1, 
column two contains lines unique to FILE2, and
column three contains lines common to both files.

Las opciones -1 -2 '-3' 'suprimen las columnas respectivas. Supongamos que desea registrar los archivos que se agregaron a /usr después de ejecutar el comando $ 1 : <code bash> # before, make install, after find /usr > “$tmp/before” $1 find /usr > “$tmp/after” # sort sort “$tmp/before” > “$tmp/before-sorted” sort “$tmp/after” > “$tmp/after-sorted” # create log comm -13 “$tmp/before-sorted” “$tmp/after-sorted” > “$log/$name” </code> Tenga en cuenta que comm requiere archivos ordenados. Aquí -1 suprime las líneas exclusivas de antes, -3 suprime las líneas presentes en ambos archivos, por lo que queda con la columna 2 que contiene archivos exclusivos después de los archivos agregados. A muchas personas les gustaría usar diff para comparar archivos, pero es principalmente para crear parches. === while read line === This construct is common and is useful for reading files or stdin one line at a time. Here is an example that can be used to concatenate split files in order: <code bash> base=“$(echo “$@” | rev | cut -d. -f1 –complement | rev)” ls -1 “$base”.* | sort -V | while read line do cat “$line” » “$base” done </code> Also note that sort -V is a version sort and is useful in cases where ls sorts suffixes incorrectly. The usual way to prevent this is to name numbered suffixes with 0 padding like file.001, but it may overflow and this is why sort -V is useful. === for i in === Here is an example for extracting all rpms in a directory: <code bash> for i in *.rpm do rpm2cpio “$i” | cpio -id –quiet done </code> You can also use seq to make i a loop counter: <code bash> for i in $(seq 1 100) do echo “$i” done </code> Note that there are no quotes around $(seq) because otherwise it would quote the entire expanded number sequence and that wouldn't work right. == External Links === * http://www.commandlinefu.com/commands/browse ==== Quoting ==== Quoting may seem complicated, and reasons for it obscure, but there is a purpose to it and it is not that complicated. === Double quoting === The reason for double quoting is to preserve spaces, like spaces in file names. Double quoting a variable or command substitution makes it into a single argument. An example: <code bash> bash-4.2$ ls file with spaces.txt filewithoutspaces.txt bash-4.2$ rm -f file with spaces.txt bash-4.2$ ls file with spaces.txt filewithoutspaces.txt bash-4.2$ rm -f “file with spaces.txt” bash-4.2$ ls filewithoutspaces.txt bash-4.2$ rm -f filewithoutspaces.txt bash-4.2$ ls bash-4.2$ </code> Clearly you need to quote a file with spaces. You could use single quotes here, because no variables were inside the quotes. You should not quote in this case: <code bash> bash-4.2$ for i in $(seq 1 10); do printf “$i ”; done; echo; 1 2 3 4 5 6 7 8 9 10 bash-4.2$ for i in “$(seq 1 10)”; do printf “$i ”; done; echo; 1 2 3 4 5 6 7 8 9 10 bash-4.2$ </code> Nor should you quote in any case where a command requires multiple variables and you give them to it inside one quoted variable. A quoted variable is then taken as the only argument, rather than multiple arguments. An example: <code> bash-4.2$ ls file with spaces.txt filewithoutspaces.txt bash-4.2$ file1=“file with spaces.txt” bash-4.2$ file2=“filewithoutspaces.txt” bash-4.2$ rm -f “$file1 $file2” bash-4.2$ ls file with spaces.txt filewithoutspaces.txt bash-4.2$ rm -f “$file1” “$file2” bash-4.2$ ls bash-4.2$ </code> Also note that you can and should quote within command substitutions, as shown by the replace a suffix example above and: <code bash> mkdir “$(basename “$(pwd)”)” </code> This makes a directory within the current directory called the same name as the current directory. If pwd expands into something with spaces, the command will work. === Single quoting === The reason for single quoting is to escape special characters from the shell, while passing them to a command so it can use them. You should use single quotes for every argument passed to another program that contains shell characters to be interpreted by that program and NOT by the shell. Example: <code bash> bash-4.2$ find -name *.txt ./list.txt bash-4.2$ find -name '*.txt' ./list.txt ./results/002.txt ./results/006.txt ./results/013.txt ./results/wipe.txt bash-4.2$ </code> Here the shell expands * before find sees it. You should single quote input to awk, find, sed, and grep, as each of these uses special characters that overlap with the shells', and thus they must be protected from shell expansion. === External Links === * http://www.grymoire.com/Unix/Quote.html ==== Regular expressions ==== === Basic === * . matches any single character. * \ escapes the next character. <note>Remember to escape the . using \. if you want an actual . <code> bash-4.2$ cat test.txt testtxt test.txt bash-4.2$ sed 's/.txtg' test.txt tes test bash-4.2$ sed 's/\.txtg' test.txt testtxt test </code></note> * [] is a class and matches anything inside the brakets for a single character. Examples: * [Yy] matches Y or y. * [a-z0-9] includes a range, and in this case matches a through z and 0 through 9. * [^a-z] negates the range, so in this case it matches anything but a through z. * ^ matches the beginning of a line. Example: ^a matches an a at the beginning of a line. * $ matches the end of a line. Example: a$ matches an a at the end of a line. * \< matches the beginning of a word. Example: \<a matches an a at the beginning of a word. * \> matches the end of a word. Example: a\> matches an a at the end of a word. * Example: \<[tT]he\> matches the word the or The. * * matches any number of the previous character or nothing = no character. Example: [0-9]* which will match any number of numbers. .* matches any number of anything. === Extended regular expressions === The following must be supported by the program for them to work. For example for grep you must run egrep or grep -E. * + matches any number of the previous character, like *, but there must be at least one to match, so it will not match nothing or no character. * ? makes the previous character optional (it can be missing), and is matched at most once. * (|) acts like an OR statement. Example: (it|her|this) matches any of those words. * a{3} matches aaa = 3 a's. * a{4,8} matches an a at least 4 times and at max 8 times, so aaaa, aaaaa, aaaaaa, aaaaaaa, and aaaaaaaa. * {0,} = * * {1,} = + * {,1} = ? === External Links === * http://www.grymoire.com/Unix/Regular.html * http://www.regular-expressions.info/ ==== Useful commands and info ==== === stat === Stat is the most accurate way to determine: * File size in bytes: <code bash>stat -c '%s' file.txt</code> * File permissions in octal: <code bash>stat -c '%a' file.txt</code> === awk variable defaults === An important point is that awk variables are set to zero by default. This may cause problems in some situtations. Example: <code bash> echo -ne '-321\n-14\n-1\n-34\n-4\n' | awk 'BEGIN{max=“”}{if ($1 > max) max=$1; if ($1 < min) min=$1;}END{print min“\t”max}' </code> This works properly because max is set to an empty string and thus has a lower value than any number. Try removing the BEGIN clause and see what happens. Also note that adding min=“” to the BEGIN clause fails as well. === no data directory test === You can use this to test if a directory contains no data. For example, it will say 0 if the directory only contains empty files and directories = no data. <code bash> du -s directory </code> === cmp === This can compare two files byte by byte, and can be more useful than checksums. For example, after you burn a CD/DVD, you can run: <code bash> cmp slackware.iso /dev/sr0 </code> It should say the following if the disk burned correctly: <code bash> cmp: EOF on slackware.iso </code> === shell math === Remember that shell utilities like let and expr only do integer math. For floating point use either bc or awk. === shell GUI === There are numerous programs that allow you to create GUIs from a shell script. * Xdialog is fully dialog compatible. * A function library that increases shell GUI portability. * Gtkdialog has advanced features for customized GUIs. === External Links === * Guide to awk, bash, sed, find, and more * Advanced bash guide * Cheat sheets on Linux CLI programs, the main site is also useful * Guide to file permissions ====== Sources ====== * I quoted man comm * I used man grep'' for the regex section.

 es:howtos:general_admin:cli_constructs_and_useful_info ()