2012-07-30 13 views
9

Digamos que tengo los siguientes archivos en mi directorio actual:Bash comando para mover solo algunos archivos?

1.jpg 
1original.jpg 
2.jpg 
2original.jpg 
3.jpg 
4.jpg 

¿Existe un comando de terminal/bash/Linux que puede hacer algo como

if the file [an integer]original.jpg exists, 
    then move [an integer].jpg and [an integer]original.jpg to another directory. 

Ejecución de una instrucción tal causará 1. jpg, 1original.jpg, 2.jpg y 2original.jpg para estar en su propio directorio.

NOTA Esto no tiene por qué ser un comando. Puedo ser una combinación de comandos simples. Tal vez algo como copiar archivos originales a un nuevo directorio. A continuación, realice un filtro de expresiones regulares en los archivos del directorio nuevo para obtener una lista de nombres de archivos del directorio anterior que aún necesita copiarse, etc.

+3

Es por esto que los superusuarios aprenden la programación :) Buena pregunta. –

+0

¿Tienes que preocuparte por el caso donde podría haber, digamos, '5original.jpg' pero no' 5.jpg'? –

Respuesta

6

Al activar el soporte glob extendido, podrá escribir un patrón similar a la expresión regular. Esto puede manejar archivos con enteros de varios dígitos, como '87 .jpg 'y' 87original.jpg '. Expansión del parámetro Bash puede usarse para quitar "original" del nombre o f un archivo encontrado para permitirle mover los dos archivos relacionados entre sí.

shopt -s extglob 
for f in +([[:digit:]])original.jpg; do 
    mv $f ${f/original/} otherDirectory 
done 

en un patrón extendido, +(x) partidos una o más de las cosas dentro de los paréntesis, análoga a la expresión regular x+. Aquí, x es cualquier dígito. Por lo tanto, unimos todos los archivos en el directorio actual cuyo nombre consta de 1 o más dígitos seguidos de "original.jpg".

${f/original/} es un ejemplo de la sustitución de patrón de bash. Elimina la primera aparición de la cadena "original" del valor de f. Entonces, si f es la cadena "1original.jpg", entonces ${f/original/} es la cadena "1.jpg".

-1

Puede usar declaraciones Regex para buscar "coincidencias" en los nombres de archivos que estás mirando a través de Luego realice sus acciones en las "coincidencias" que encuentre.

+1

gracias, ¿puede mostrar una solución de ejemplo basada en los nombres de archivo mencionados anteriormente? Aprendo mejor viendo soluciones de muestra – John

-1

integer=0; while [ $integer -le 9 ] ; do if [ -e ${integer}original.jpg ] ; then mv -vi ${integer}.jpg ${integer}original.jpg lol/ ; fi ; integer=$[ $integer + 1 ] ; done

Tenga en cuenta que aquí, "lol" es el directorio de destino. Puedes cambiarlo a cualquier cosa que quieras. Además, puede cambiar el 9 en while [ $integer -le 9 ] para verificar números enteros mayores a 9. Ahora mismo comienza en 0 * y se detiene después de marcar 9 *.

Editar: Si lo desea, puede reemplazar los puntos y comas en mi código con retornos de carro y puede ser más fácil de leer. Además, puede pegar todo el bloque en la terminal de esta manera, incluso si eso no fuera inmediatamente obvio.

+3

Debería considerar formatear su código de forma que sea fácil de leer y mantener. – jordanm

3

así, no directamente, pero es una oneliner (edit: no más):

for i in [0-9].jpg; do 
    orig=${i%.*}original.jpg 
    [ -f $orig ] && mv $i $orig another_dir/ 
done 

edición: Probablemente debería señalar que mi solución:

  • for i in [0-9].jpg: ejecutar el cuerpo del ciclo de cada archivo jpg con un número como nombre de archivo. almacenar el nombre de archivo en toda $i
  • orig={i%.*}original.jpg: salvo en $orig la posible nombre para el "archivo original"
  • [ -f $orig ]: comprobar a través de test(1) (las cosas [ ... ]) si existe el archivo original para $i. si es así, mueva ambos archivos al another_dir. esto se hace a través de &&: la parte posterior solo se ejecutará si la prueba fue exitosa.
+1

Debe formatear su código en varias líneas para que sea más fácil de leer. Además, puedes evitar utilizar basename con '$ {i ## * /}' en su lugar. – jordanm

+0

gracias. es una buena idea evitar el nombre base y el uso de patrones, pero '$ {i ## * /}' no funcionó para mí. Usé '$ {i%. *}' En su lugar. – lewurm

1

El siguiente iba a funcionar y es fácil de entender (sustituir out con el directorio de salida, y {1..9} con el alcance real de sus números.

for x in {1..9} 
do 
if [ -e ${x}original.jpg ] 
then 
mv $x.jpg out 
mv ${x}original.jpg out 
fi 
done 

es obvio que puede también entrar en él como una sola línea

+3

Bajar votaciones de respuestas perfectamente válidas sin una explicación no tiene sentido ... – houbysoft

2

Esto debería funcionar para cualquier prefijo estrictamente numérico, es decir 234.jpg

for f in *original.jpg; do 
    pre=${f%original.jpg} 
    if [[ -e "$pre.jpg" && "$pre" -eq "$pre" ]] 2>/dev/null; then 
    mv "$f" "$pre.jpg" targetDir 
    fi 
done 

"$pre" -eq "$pre" da un error si no enteros

EDIT:
esto falla si existen original.jpg y .jpg ambos.
$pre es entonces nullstring y "$pre" -eq "$pre" es verdadero.

Cuestiones relacionadas