scripts script recibe que por pasar parametros ejemplos ejecutar con bash parameters

recibe - scripts bash ejemplos



Extraiga los parámetros antes del último parámetro en "$ @" (14)

Estoy tratando de crear una secuencia de comandos Bash que extraiga el último parámetro dado de la línea de comandos en una variable que se utilizará en otro lugar. Aquí está el guión en el que estoy trabajando:

#!/bin/bash # compact - archive and compact file/folder(s) eval LAST=/$$# FILES="$@" NAME=$LAST # Usage - display usage if no parameters are given if [[ -z $NAME ]]; then echo "compact <file> <folder>... <compressed-name>.tar.gz" exit fi # Check if an archive name has been given if [[ -f $NAME ]]; then echo "File exists or you forgot to enter a filename. Exiting." exit fi tar -czvpf "$NAME".tar.gz $FILES

Dado que los primeros parámetros pueden ser de cualquier número, tengo que encontrar una forma de extraer el último parámetro (por ejemplo, archivo compacto.un archivo.b archivo.d archivos-abd.tar.gz). Como está ahora, el nombre del archivo se incluirá en los archivos para compactar. ¿Hay alguna forma de hacer esto?


Soluciones portátiles y compactas.

Así es como lo hago en mis guiones.

last=${@:$#} # last parameter other=${*%${!#}} # all parameters except the last

EDITAR
Según algunos comentarios (ver más abajo), esta solución es más portátil que otras.
Por favor, lea el comentario de Michael Dimmitt para una explicación de cómo funciona.


¿Estás seguro de que este elegante script es mejor que un simple alias para tar?

alias compact="tar -czvpf"

El uso es:

compact ARCHIVENAME FILES...

Donde ARCHIVOS pueden ser file1 file2 o globos como *.html


Agregaría esto como un comentario, pero no tengo suficiente reputación y la respuesta se alargó un poco de todos modos. Espero que no le importe.

Como dijo @func:

last_arg = "$ {! #}"

Cómo funciona:

$ {! PARAM} indica el nivel de direccionamiento indirecto. No hace referencia a PARAM en sí, sino al valor almacenado en PARAM (piense en PARAM como puntero a valor).
$ {#} se expande a la cantidad de parámetros (Nota: $ 0 - el nombre del script - no se cuenta aquí).

Considere la siguiente ejecución:

$./myscript.sh p1 p2 p3

Y en el myscript.sh

#!/bin/bash echo "Number of params: ${#}" # 3 echo "Last parameter using ''/${!#}'': ${!#}" # p3 echo "Last parameter by evaluating positional value: $(eval LASTP=''$''${#} ; echo $LASTP)" # p3

Por lo tanto, puede pensar en $ {! #} Como un atajo para el uso de evaluación anterior, que hace exactamente el enfoque descrito anteriormente: evalúa el valor almacenado en el parámetro dado, aquí el parámetro es 3 y mantiene el argumento posicional $ 3

Ahora, si desea todos los parámetros excepto el último, puede usar la eliminación de la subcadena $ {PARAM% PATTERN}, donde el signo % significa "eliminar el patrón de coincidencia más corto del final de la cadena" .

De ahí en nuestro guión:

echo "Every parameter except the last one: ${*%${!#}}"


Puedes leer algo aquí: Expansión de parámetros


Array sin último parámetro:

array=${@:1:$#-1}

Pero es un bashism :(. Las soluciones adecuadas implicarían el cambio y la adición de variables a medida que otros lo usan.


Este script puede funcionar para usted: devuelve un subrango de los argumentos y puede llamarse desde otro script.

Ejemplos de ello corriendo:

$ args_get_range 2 -2 y a b "c 1" d e f g ''b'' ''c 1'' ''d'' ''e'' $ args_get_range 1 2 n arg1 arg2 arg1 arg2 $ args_get_range 2 -2 y arg1 arg2 arg3 "arg 4" arg5 ''arg2'' ''arg3'' $ args_get_range 2 -1 y arg1 arg2 arg3 "arg 4" arg5 ''arg2'' ''arg3'' ''arg 4'' # You could use this in another script of course # by calling it like so, which puts all # args except the last one into a new variable # called NEW_ARGS NEW_ARGS=$(args_get_range 1 -1 y "$@")

args_get_range.sh

#!/usr/bin/env bash function show_help() { IT=" Extracts a range of arguments from passed in args and returns them quoted or not quoted. usage: START END QUOTED ARG1 {ARG2} ... e.g. # extract args 2-3 $ args_get_range.sh 2 3 n arg1 arg2 arg3 arg2 arg3 # extract all args from 2 to one before the last argument $ args_get_range.sh 2 -1 n arg1 arg2 arg3 arg4 arg5 arg2 arg3 arg4 # extract all args from 2 to 3, quoting them in the response $ args_get_range.sh 2 3 y arg1 arg2 arg3 arg4 arg5 ''arg2'' ''arg3'' # You could use this in another script of course # by calling it like so, which puts all # args except the last one into a new variable # called NEW_ARGS NEW_ARGS=/$(args_get_range.sh 1 -1 /"/$@/") " echo "$IT" exit } if [ "$1" == "help" ] then show_help fi if [ $# -lt 3 ] then show_help fi START=$1 END=$2 QUOTED=$3 shift; shift; shift; if [ $# -eq 0 ] then echo "Please supply a folder name" exit; fi # If end is a negative, it means relative # to the last argument. if [ $END -lt 0 ] then END=$(($#+$END)) fi ARGS="" COUNT=$(($START-1)) for i in "${@:$START}" do COUNT=$((COUNT+1)) if [ "$QUOTED" == "y" ] then ARGS="$ARGS ''$i''" else ARGS="$ARGS $i" fi if [ $COUNT -eq $END ] then echo $ARGS exit; fi done echo $ARGS


Gracias chicos, lo hicieron, aquí está el último guión de bash:

#!/bin/bash # compact - archive and compress file/folder(s) # Extract archive filename for variable ARCHIVENAME="${!#}" # Remove archive filename for file/folder list to backup length=$(($#-1)) FILES=${@:1:$length} # Usage - display usage if no parameters are given if [[ -z $@ ]]; then echo "compact <file> <folder>... <compressed-name>.tar.gz" exit fi # Tar the files, name archive after last file/folder if no name given if [[ ! -f $ARCHIVENAME ]]; then tar -czvpf "$ARCHIVENAME".tar.gz $FILES; else tar -czvpf "$ARCHIVENAME".tar.gz "$@" fi


No puedo encontrar una manera de usar la notación de subíndice de matriz en $@ , por lo que esta es la mejor que puedo hacer:

#!/bin/bash args=("$@") echo "${args[$(($#-1))]}"


Para eliminar el último elemento de la matriz, podría usar algo como esto:

#!/bin/bash length=$(($#-1)) array=${@:1:$length} echo $array


Solo eliminando la variable de length utilizada en la solución de Krzysztof Klimonda:

( set -- 1 2 3 4 5 echo "${@:1:($#-1)}" # 1 2 3 4 echo "${@:(-$#):($#-1)}" # 1 2 3 4 )


Tratar:

if [ "$#" -gt ''0'' ]; then /bin/echo "${!#}" "${@:1:$(($# - 1))} fi


Ya se han publicado varias soluciones; sin embargo, aconsejaría reestructurar su script para que el nombre del archivo sea el primer parámetro en lugar del último. Entonces es realmente sencillo, ya que puedes usar el shift incorporado para eliminar el primer parámetro:

ARCHIVENAME="$1" shift # Now "$@" contains all of the arguments except for the first


#!/bin/bash lastidx=$# lastidx=`expr $lastidx - 1` eval last=''$''{$lastidx} echo $last


last_arg="${!#}"


#!/bin/sh eval last=''$''$# while test $# -gt 1; do list="$list $1" shift done echo $list $last