Primero haré una base de prueba: 5 archivos y una carpeta:
touch file1 file2 file3 file4 file5
mkdir folder
A continuación, ejecutaré un comando de prueba. La -vopción especifica que quiero que se impriman todos los comandos que ejecuta el shell stderr. La -xopción especifica que quiero que se imprima lo mismo stderr, pero quiero que se haga después de evaluar el comando pero antes de que el shell lo ejecute.
sh -cxv 'echo mv *'
SALIDA
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
Entonces verá que el comando que le doy al shell es echo mv *y el comando que ejecuta el shell después de * expandirse es echo mvseguido por todos esos archivos y la carpeta.
Por defecto, el shell expandirá globos como:
sh -cxv 'echo file[1-5]'
SALIDA
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
Este es el resultado de la set [+-]ffunción glob:
sh -cxvf 'echo file[1-5]'
SALIDA
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
Entonces, cuando ejecuta un comando en un shell configurado con opciones predeterminadas como mv *el shell, se expande en la *palabra una lista de argumentos de todos los archivos en el directorio actual ordenados de acuerdo con la configuración regional. Realiza la llamada exec(ve)al sistema mv (esencialmente) con esta lista de argumentos adjunta. Entonces mvobtiene todos los argumentos a medida que el shell los engloba y los ordena. Además stracede ver estos efectos, puede usar la depuración nuevamente como:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
SALIDA
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
Y portablemente:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
SALIDA
: /mv/file1/file2/file3/file4/file5/folder/
Básicamente, el shell se ejecuta mvcon el contenido del directorio (si no está vacío y no incluye archivos / carpetas con nombres que comienzan con .) como su lista de argumentos. mves POSIX especifica para interpretar su argumento final como un directorio si se invoca con más de dos argumentos - de la misma manera lnes (porque, de hecho, son herramientas muy similares en función subyacente) .
Sin echoembargo, es suficiente :
sh -cxv 'mv *' ; ls
SALIDA
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
Todos los archivos se movieron al argumento final, porque es una carpeta. ¿Y si no es una carpeta?
sh -cxv 'cd *; mv *'; ls . *
SALIDA
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
Así es como debería comportarse POSIX especifica mv en ese caso:
mv [-if] source_file target_file
mv [-if] source_file... target_dir
En la primera forma de sinopsis, la mvutilidad moverá el archivo nombrado por el operando source_file al destino especificado por el archivo target_file . Esta primera forma de sinopsis se supone cuando el operando final no nombra un directorio existente y no es un enlace simbólico que se refiere a un directorio existente. En este caso, si el archivo de origen nombra un archivo que no es de directorio y el archivo de destino finaliza con un /slashcarácter final , mvse tratará como un error y no se procesarán operandos de archivo de origen .
En la segunda forma de sinopsis, mvmoverá cada archivo nombrado por un operando de archivo de origen a un archivo de destino en el directorio existente nombrado por el operando target_dir , o referenciado si target_dir es un enlace simbólico que se refiere a un directorio existente. La ruta de destino para cada archivo de origen será la concatenación del directorio de destino, un solo /slashcarácter si el destino no terminó en a /slash, y el último componente de nombre de ruta del archivo de origen . Se asume esta segunda forma cuando el operando final nombra un directorio existente.
Entonces, si se *expande a: