Acabo de perder una pequeña parte de mi colección de audio, por un estúpido error que cometí. :-(
DIVERTIDO Tenía una copia de seguridad bastante reciente, pero aún así era irritante. Aparte de la suya, el otro culpable que hizo la travesura fue mv, que se mostrará de la siguiente manera:
Los archivos de audio tenían un cierto esquema:
ARTIST - Some Title YY.mp3
donde YYes la especificación año de 2 dígitos.
mkdir 90<invisible control character>
(¡Hasta este momento, no sabía que había escrito un tercer carácter en exceso que era invisible ...!)
En lugar de tener todo en un directorio, quería tener toda la música de los 90 en un solo directorio. Entonces escribí:
find . -name '* 9?.mp3' -exec mv {} 90 \;
No es tan difícil de conseguir la idea de lo que sucedió eh? : ->
El (desastroso) resultado fue una virgen vacío directorio llamado '90 algo '(con algo de ser el carácter de control 'invisible') y un solo archivo llamado '90', sobrescritos n veces.
TODOS LOS ARCHIVOS habían desaparecido. : - (((obviamente)
Wish mvhubiera verificado a tiempo si la firma del "archivo" de destino (recuerde en * NIX: Everything Is A File ) comienza con un d------(por ejemplo drwxr-xr-x). Y, por supuesto, si el destino existe en absoluto. Hay una variante del escenario antes mencionado, en las que simplemente se olvidó de mkdirla guía en primer lugar. (pero por supuesto, asumiste que está ahí ...)
Incluso nuestra mascota OS-odio empezando por la capital W hace este. Incluso se le solicita que especifique el tipo de destino (¿archivo? ¿Directorio?) Si lo solicita.
Por lo tanto, me pregunto si nosotros * NIXers todavía tenemos que escribirnos un " mvscriptlet" solo para evitar este tipo de sorpresas no deseadas.

.mp3debería estar allí con el nombre90, podría haber sido uno para el que no tenía una copia de seguridad.mvno es el problema aquí, técnicamente, no sabe que usted está en movimiento una serie de archivos. Está ejecutandomvuna vez para cada archivo. Así es comofind -exec ;funciona. Si lo hubiera usadofind -exec +(como en algunos de los comentarios)mvhabría gritado tan pronto como recibiera más de un argumento.mvde cada archivo puede parecer un poco menos pensada al principio, será (como dije anteriormente) la única solución sensata una vez que los archivos de origen estén dispersos entre varios subdirectorios. Que en mi caso de prueba, los archivos de origen estaban todos en un directorio no significa que sea mi caso de prueba real . Es, de hecho, sólo una simplificación, porque puede elaborar fácilmente en que por mi cuenta más adelante. Además, se hace preguntas menos tiempo para leer debido a su longitud reducida. :)mvrequerir que exista el destino?mv oldfile newfilees la forma de cambiar el nombre de un archivo, y es una tontería esperarnewfileque ya exista y sea un directorio.Respuestas:
Se puede añadir una
/al destino si desea mover los archivos a un directorio. En caso de que el directorio no exista, recibirá un error:En caso de que el directorio exista, mueve el archivo a ese directorio.
fuente
GNU coreutils
mvya tiene una opción que especifica que desea mover a un directorio:-t/--target-directory. Si el argumento de esa opción no existe,mvse quejará en lugar de mover todos sus archivos al mismo nombre de archivo.Yo habría escrito su motor de la siguiente manera:
Tenga en cuenta el uso de, en
+lugar de\;, agrupar tantos nombres de archivos como sea posible, lo que resulta en una ejecución más rápida.fuente
find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +Además, si generalmente planea evitar sobrescrituras accidentales en el futuro, existe la
-iopciónmv. Personalmente no puedo pensar en ningún inconveniente si ustedSi necesita sobrescribir algo, simplemente pase la
-fopción.Los alias solo surten efecto si escribe el comando directamente en un shell interactivo, no para casos como invocación por
find. Podrías haber corridoy luego se le habría preguntado si
mvhubiera intentado sobrescribir un archivo existente.fuente
mv. Este "truco" menos conocido hará que el comando con la barra diagonal inversa antepuesta ignore cualquier definición de alias.find ... -exec mv ..., entonces necesitarás crear~/bin/mv(o algún otro directorio apropiado) y hacerlo/bin/mv -i "$@", porquefind ... -execno mira los alias.env mv. Menos mecanografía. :) Como mi diseño de teclado local requiere que se presione la tecla MAYÚS para una barra diagonal, siempre preferiría las versiones sin barra (si corresponde).mven una ubicación al principio$PATHsería una solución más limpia. Por otro lado me primarly la casualidad de quemvpor descuido en el intérprete de comandos interactivo (porque pasa rápido). En el momento en que compongo algo más complejo, comofindunforbucle o incluso un script de shell, tiendo a realizar algunas ejecuciones en seco (usandoecho) para asegurarme de no romper algo. En aquellos casos en que no necesito una mano de retenciónmv, porque ya estoy poniendo algunos pensamientos en ella.Además de las excelentes respuestas anteriores, me gustaría aclarar por qué no recibió la pregunta sobre si se debe mover los archivos o no.
Si se mueve un archivo a un nuevo nombre, y ese nombre no es un directorio,
mvse cambie el nombre del archivo con el nuevo nombre.El problema aquí es que estaba utilizando
findpara ejecutarmvuna vez por archivo , no una vez para todos los archivos .Si, en cambio, se había hecho
mv *90.mp3 90, entoncesmvhabría fallado con el mensaje de error que "el archivo de destino no es un directorio".Otro consejo es utilizar la implementación del tabulador al escribir la ruta de destino. Se le mostrará si el destino es un directorio añadiendo
/al nombre de destino. También puede utilizarmv -ique se le pregunte si desea sobrescribir un archivo existente.fuente
mv *90.mp3 90, mv habría fallado con el mensaje de error de que "el archivo de destino no es un directorio". Ja, sí, ¿por qué tan complicado eh? Uso tu línea y seré feliz. Sin embargo, solo en este caso trivial. :) Porque esta es la forma normal en que hago mis preguntas: las reduciría por simplicidad. Nadie se ha opuestofindhasta ahora considerando que los archivos de los 90 también podrían estar dispersos en varios subdirectorios que también quiero "atrapar". Si y solo si siempre están en un directorio de origen, sumvlínea es aplicable.mvcomporta, no como una crítica de su elección de herramientas.findymv, por ejemplofind /music -type d -exec mv {}/*90.mp3 targetdir\;- pero ahora me siento un poco como estoy complicar excesivamente, y el simple uso-io-tes más eficientefind . -type d -exec mv {}/*9?.mp3 target \;ejemplo funcionó, todavía existiría el riesgo de que elmvcomando se veamv file targetpara cada directorio que contenga solo un*9?.mp3archivo; por lo que todos esos archivos (excepto el último) se perderían.*.mp3archivos en un árbol de directorios, se podíashopt -s globstary ejecute el comando en**/*.mp3- el**actuará como unafind.Como una estrategia alternativa de uso general, me gustaría sugerir convertir este tipo de operación en un script temporal. Prefiero mirar los resultados
findy convertirlos en unmvcomando a mano, asegurando que entiendo lo que estoy haciendo antes de ejecutar. p.ej.Ahora puedo mirar a través de una lista de nombres de archivo y volver a escribir el contenido del archivo como un comando shell.
ggVGJImv[esc]Asomedir/[esc]source tmpen la línea de comando.Es una estrategia conservadora, pero he sido mordido con demasiada frecuencia por comandos mal escritos
-execosedexpansiones de shell mal entendidas, y prefiero adoptar un enfoque lento y consistente.En otras palabras: soy demasiado cobarde para usar
-exec.fuente
:%s/.*/"&"/paso, porque, en este caso, sabe que cada nombre de archivo contiene al menos un espacio.echo mvlugar de ejecutarlosmvy luego eliminarlosechosi está satisfecho.Otra opción:
es lo mismo que -i, pero no preguntará, fallará.
fuente