
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
mv1 *.png
Sólo mueve el primer .png
archivo que encuentra, no todos.
¿Cómo puedo hacer que el comando se aplique a todos los archivos que coincidan con los comodines?
Respuesta1
mv1 *.png
primero expande el patrón comodín *.png
en la lista de nombres de archivos coincidentes y luego pasa esa lista de nombres de archivos a la función.
Luego, dentro de la función $1
significa: tomar el primer argumento de la función, dividirlo donde contenga espacios en blanco y reemplazar cualquiera de las partes separadas por espacios en blanco que contengan caracteres comodín y hacer coincidir al menos un nombre de archivo con la lista de nombres de archivos coincidentes. ¿Suena complicado? Lo es, y este comportamiento sólo es útil ocasionalmente y a menudo es problemático. Este comportamiento de división y coincidencia solo ocurre si $1
ocurre fuera de comillas dobles, por lo que la solución es fácil: use comillas dobles.Coloque siempre comillas dobles alrededor de las sustituciones de variables.a menos que tengas una buena razón para no hacerlo.
Por ejemplo, si el directorio actual contiene los dos archivos A* algorithm.png
y graph1.png
, mv1 *.png
pasa A* algorithm.png
como primer argumento a la función y graph1.png
como segundo argumento. Luego $1
se divide en A*
y algorithm.png
. El patrón A*
coincide A* algorithm.png
y algorithm.png
no contiene caracteres comodín. Entonces la función termina ejecutándose mv
con los argumentos -n
, A* algorithm.png
, y . Si corrige la función aalgorithm.png
targetdir
-v
function mv1 { mv -n "$1" "targetdir" -v |wc -l ;}
entonces moverá correctamente el primer archivo.
Para procesartodolos argumentos, dígale al shell que procese todos los argumentos y no solo el primero. Puede usar "$@"
para referirse a la lista completa de argumentos pasados a la función.
function mv1 { mv -n "$@" "targetdir" -v |wc -l ;}
Esto es casi correcto, pero aún falla si el nombre de un archivo comienza con el carácter -
, porque mv
tratará ese argumento como una opción. Pase --
a mv
para decirle "no más opciones después de este punto". Esta es una convención muy común que admiten la mayoría de los comandos.
function mv1 { mv -n -v -- "$@" "targetdir" |wc -l ;}
Un problema restante es que si mv
falla, esta función devuelve un estado de éxito, porque se ignora el estado de salida de los comandos en el lado izquierdo de una tubería. En bash (o ksh), puede utilizarlo set -o pipefail
para hacer que la canalización falle. Tenga en cuenta que configurar esta opción puede causar que otro código que se ejecuta en el mismo shell falle, por lo que debe configurarlo localmente en la función, lo cual es posible desde bash 4.4.
function mv1 {
local -
set -o pipefail
mv -n -v -- "$@" "targetdir" | wc -l
}
En versiones anteriores, la configuración pipefail
sería frágil, por lo que sería mejor verificarla PIPESTATUS
explícitamente.
function mv1 {
mv -n -v -- "$@" "targetdir" | wc -l
((!${PIPESTATUS[0] && !${PIPESTATUS[1]}}))
}
Respuesta2
$1
es el primer argumento de la función, aquí el primer archivo que coincide *.png
. Supongo que eso "$@"
es lo que quieres usar en lugar de $1
.
Respuesta3
Tendrías que usar mv1 \*.png
.
Al interactuar con funciones, la Terminal de Linux no pasa el asterisco directamente al comando, sino que selecciona el primer parámetro coincidente y lo pasa al comando.
Para permitir que el asterisco pase directamente, es necesario escapar del asterisco mediante una barra invertida.