Estoy tratando de entender esta línea desde un script de shell. Sé que eso $(..)
significa ejecutar ..
e insertar su salida donde la encuentre $()
en una declaración. Pero ¿qué pasa entre esos paréntesis? ¿Qué es el \ls
hacer y cómo se relaciona con lo \
de las líneas anteriores? ¿Es eso una \\
división en dos líneas? ¿Es \ls
lo mismo que el normal ls
?
APPCLASSPATH=$CLASSPATH:$({ \
\ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \
\ls -1 "$VOLTDB_LIB"/*.jar; \
\ls -1 "$VOLTDB_LIB"/extension/*.jar; \
} 2> /dev/null | paste -sd ':' - )
Respuesta1
La salida de los 3 ls
comandos se pasa al paste
comando que los fusiona en el valor:
$VOLTDB_VOLTDB"/voltdb-*.jar:$VOLTDB_LIB"/*.jar:$VOLTDB_LIB"/extension/*.jar
NOTA:Las variables $VOLTDB_VOLTDB
y $VOLTDB_LIB
se expandirán y puede haber más valores que un solo archivo para cada uno de estos ls
comandos. ¿Ves *
ahí? Es un carácter global que actúa como comodín y se expande a cualquier cosa entre el lado izquierdo (voltdb-) y el lado derecho (.jar), por ejemplo.
Estos coincidirían:
voltdb-1.jar
voltdb-blah.jar
voltdb-12345.jar
Entonces todo se incluye en la variable APPCLASSPATH
:
APPCLASSPATH=$CLASSPATH:$VOLTDB_VOLTDB"/voltdb....etc.
El comando pegar
Aquí hay un ejemplo en el que estoy usando el seq
comando para generar una secuencia de números, del 1 al 10.
$ seq 10 | paste -sd ':' -
1:2:3:4:5:6:7:8:9:10
Puede ver que el paste
comando fusiona la salida y la separa con dos puntos ( :
).
También puedes imitar el comando de ejemplo de esta manera:
$ { echo "hi1"; echo "hi2"; echo "hi3"; } | paste -sd ':' -
hi1:hi2:hi3
NOTA:El -
comando pegar le indica que tome la entrada de STDIN e imprima cada argumento a medida que ingresa, separado por un archivo :
.
Con diferentes cambios paste
también se puede dividir los datos en grupos, según el número de -
's que siguen.
Pegar ejemplos
Aquí hay un ejemplo con 2 -
.
$ seq 10 | paste - -
1 2
3 4
5 6
7 8
9 10
Aquí hay 3 -
.
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
Entonces indica paste
cuántos argumentos paste
deben imprimirse en cada línea. Pero no se confunda, el ejemplo que está tratando es simplemente tomar la entrada de STDIN, separar cada argumento en espacios e imprimirlo seguido de un archivo :
. Al dar varios -
, le está diciendo paste
que tome argumentos, 2 y a la vez, 3 a la vez, etc.
Argumentos 2 a la vez, separados por :
's:
$ seq 10 | paste -d ':' - -
1:2
3:4
5:6
7:8
9:10
$ seq 10 | paste -d ':' - - -
1:2:3
4:5:6
7:8:9
10::
Por cierto, si incluye el -s
modificador, le está indicando paste
que tome los argumentos en serie (en serie). Observe lo que sucede cuando lo usa en uno de los ejemplos anteriores.
2 a la vez:
$ seq 10 | paste -sd ':' - -
1:2:3:4:5:6:7:8:9:10
3 a la vez:
$ seq 10 | paste -sd ':' - - -
1:2:3:4:5:6:7:8:9:10
Respuesta2
$(command)
ejecuta un comando y sustituye su salida.
{ list; }
es un comando de grupo que ejecuta varios comandos en el entorno de shell actual. Es similar a (list)
, pero no forma una subcapa.
\command
se utiliza para ignorar alias de comandos, lo que puede alterar considerablemente el comportamiento esperado de un comando.
Al \
final de la línea simplemente significa que esta línea continúa, por lo que el shell verá la siguiente línea como parte de la actual. Generalmente no es necesario cuando esto es obvio por el contexto (paréntesis abierto o cita).
Respuesta3
APPCLASSPATH=$CLASSPATH:$({ \ \ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \ \ls -1 "$VOLTDB_LIB"/*.jar; \ \ls -1 "$VOLTDB_LIB"/extension/*.jar; \ } 2> /dev/null | paste -sd ':' - )
\ls
es como ls
, excepto que si ls
es un alias, la barra invertida evita la expansión del alias. Esto garantiza que ls
se utilice el comando y no algún alias que pueda agregar resultados no deseados, como un sufijo clasificador ( -F
).
Los ls
comandos, llamados con nombres de archivos existentes como argumentos, enumeran sus argumentos, uno por línea. La opción -1
no tiene ningún efecto ya que la salida de ls
va a una tubería y no a una terminal. Si ls
recibe un argumento que no es el nombre de un archivo existente, no muestra nada en su salida estándar y en su lugar muestra un error. Los errores de los ls
comandos se redirigen a ninguna parte mediante 2> /dev/null
. Hay dos razones por las que ls
se puede recibir un argumento que no es un archivo: si una de las variables no hace referencia a un directorio existente y legible, o si no hay ningún archivo que coincida con el patrón comodín. En cualquier caso, el patrón se pasa sin expandir a ls
.
Las barras invertidas al final de las líneas hacen que el shell ignore la siguiente nueva línea. Ninguno de ellos es útil aquí ya que en cada punto donde se utilizan, el shell espera una nueva línea opcional.
Las llaves {...} agrupan los comandos. El comando compuesto { \ls …; \ls …; \ls … ; }
se canaliza paste
y sus errores se redirigen a /dev/null
.
El paste
comando une todas las líneas de entrada con un :
punto intermedio. Equivale a tr '\n' :
excepto que no pone a :
al final.
La sustitución del comando $(…)
hace que la salida de paste
se interpole en APPCLASSPATH
, después del valor de la CLASSPATH
variable con dos puntos para separar las dos partes.
Aquí hay una versión simplificada. Esto es ligeramente diferente del original en que si ninguno de los patrones comodín coincide con nada, APPCLASSPATH
será igual CLASSPATH
sin dos puntos finales adicionales (lo cual probablemente sea deseable).
APPCLASSPATH=$CLASSPATH:$(
\ls "$VOLTDB_VOLTDB"/voltdb-*.jar "$VOLTDB_LIB"/*.jar "$VOLTDB_LIB"/extension/*.jar |
tr '\n' :) 2>/dev/null
APPCLASSPATH=${APPCLASSPATH%:}