Estoy tratando de mover archivos desde la Terminal, pero solo los de los resultados de una grep
consulta.
ls -l | grep -i s02 | mv
¿Cuál es la mejor manera de completar el comando anterior?
Puede lograr esto simplemente ejecutando
cd directory/containing/the/files
mv *[sS]02* /path/to/target/
Para operaciones más complejas, también existe la opción de usar find
para encontrar todos los archivos relevantes. El ejemplo de su pregunta también podría escribirse como
cd directory/containing/the/files
find . -type f -maxdepth 1 -iname '*s02*' -exec mv {} /path/to/target/directory/ \;
Vale la pena echarle un vistazo man find
para ver qué otras opciones están disponibles.
Por ejemplo con bash. Teniendo en cuenta los archivos a continuación
$ ls -1
test1
test2
test3
1) Para evitar sorpresas, echemos un vistazo primero a los comandos.
$ for i in test*; do echo mv $i $i.ext; done
mv test1 test1.ext
mv test2 test2.ext
mv test3 test3.ext
y ejecutar los comandos si esto es lo que queremos
$ for i in test*; do mv $i $i.ext; done
$ ls -1
test1.ext
test2.ext
test3.ext
Adapta el camino a tus necesidades.
2) Es posible usar sed y xargs . Probemos primero
$ ls -1 test* | sed 'p;s/test/test_/' | xargs -n2 printf "%s %s\n"
test2 test_2
test1 test_1
test3 test_3
y ejecutar los comandos si esto es lo que queremos
$ ls -1 test* | sed 'p;s/test/test_/' | xargs -n2 mv
$ ls -1
test_1
test_2
test_3
Espacios en el nombre del archivo
Estos scripts no funcionarán como se esperaba si los nombres de archivo incluyen espacios. En Unix, el espacio se usa como separador. Por ejemplo con los archivos
$ ls -1
test 1
test 2
test 3
está claro que los comandos a continuación no pueden funcionar como se esperaba
$ for i in test*; do echo mv $i $i.ext; done
mv test 1 test 1.ext
mv test 2 test 2.ext
mv test 3 test 3.ext
La solución es excluir el espacio de la lista de separadores.
$ IFS="`printf '\n\t'`"
y agréguelo a los comandos que deben procesar los nombres de archivo con espacios. El comando de abajo
$ IFS="`printf '\n\t'`"; for i in test*; do mv $i $i.ext; done
funciona como se esperaba
$ ls -1
test 1.ext
test 2.ext
test 3.ext
La siguiente opción es la cita de los argumentos.
for i in test*; do mv "$i" "$i.ext"; done
De esta forma es posible utilizar la rica variedad de filtros de Unix y evitar la limitación a la construcción "find... -exec... {}". Para otras limitaciones, consulte las notas debajo de la línea.
Notas sobre macOS
1) Citando de opengroup.org - Estándar de producto: Comandos y utilidades V4
1.4.21 sh
Pregunta 31: ¿Se ignora la variable de entorno IFS cuando se invoca el shell?
Respuesta: Sí
Justificación: La especificación permite que el comando sh ignore la configuración de la variable de entorno IFS en la invocación. La configuración de esta variable se ha utilizado para violar la seguridad en los sistemas que utilizan el shell para interpretar una llamada a las interfaces system() y execvp().
Referencia: Norma Técnica, Shell y Utilidades, Edición 6, Capítulo 4, Utilidades, sh, VARIABLES AMBIENTALES, IFS.
2) Citando de developer.apple.com - Entrada y salida de Shell
Puede modificar el comportamiento del comando de lectura modificando la variable de shell IFS (abreviatura de separadores de campo internos). El comportamiento predeterminado es dividir las entradas dondequiera que haya un espacio, una pestaña o una nueva línea. Cambiando esta variable,...
3) Citando de developer.apple.com - Declaraciones de control básico - Estándar para bucles
En el siguiente ejemplo, la lista es *.JPG...
#!/bin/sh
for i in *.JPG ; do
mv "$i" "$(echo $i | sed 's/\.JPG$/.x/')"
mv "$(echo $i | sed 's/\.JPG$/.x/')" "$(echo $i | sed 's/\.JPG$/.jpg/')"
done
test 1
y similares. Tampoco hará lo que espera que haga si el directorio actual contiene archivos con nombres que comienzan con test
.\0
cadenas terminadas y ocuparse de configurar/usar variables es todo lo que se necesita. Consulte mywiki.wooledge.org/BashPitfalls y mywiki.wooledge.org/BashFAQ :-)for
bucle sobre el resultado de find
. Usar find ... -exec
(combinado con xargs
y/o sh -c
) es la forma canónica de Unix de hacer este tipo de cosas.
sin ladera