Tengo una lista de archivos separados por espacios en un archivo list.txt
. Me gustaría copiarlos a una nueva carpeta.
Traté de hacer:
cp `cat list.txt` new_folder
Pero no funcionó.
Cómo harías esto ?
Actualizar:
Gracias por todas sus respuestas muy interesantes. No pedí mucho :)
Después de haber probado la solución anterior por segunda vez, parece que se cp
imprimió la ayuda de uso porque la carpeta new_folder
aún no existía. Lo siento, parece ser un error estúpido ... Cuando creo la carpeta antes, funciona.
Sin embargo, he aprendido mucho de todas sus respuestas y soluciones, gracias por el tiempo que toma escribirlas.
Respuestas:
Intenta usar xargs:
Actualizar:
Hice esto en OS X, que tiene una versión diferente a las versiones de GNU / Linux. El
xargs
que proviene de GNU findutils no tiene-J
pero tiene uno-I
que es similar (como señaló Dennis Williamson en un comentario). La versión OS X de xargs tiene ambos-I
y-J
tienen comportamientos ligeramente diferentes: cualquiera funcionará para esta pregunta original.fuente
xargs
no tiene-J
lo-I
que parece hacer lo mismo. ¿Qué versiónxargs
y qué sistema operativo / distribución tienes?xargs --version
devuelve un mensaje de error de uso. Es probable que sea una versión BSD de xargs. El uso de-I
y-J
son sutilmente diferentes. Actualizaré mi respuesta con ejemplos bien formateados.-J
y-I
:)No es necesario
cat
en absoluto:O usando opciones largas:
Aquí hay algunas versiones de shell. Tenga en cuenta que algunas variables no están entre comillas o los
for
bucles se usan específicamente porque el OP especificó que los nombres de los archivos están delimitados por espacios. Algunas de estas técnicas no funcionarán para la entrada de nombre de archivo por línea en la que los nombres de archivo contienen espacios en blanco.Golpetazo:
o
sh (o Bash):
o
o
o
fuente
-t
necesita enxargs -a list.txt cp -t new_folder
?-t
es una opción decp
. Copia todos los argumentos de origen en el directorio de destino especificado. Aquí, permite especificar el objetivo antes que la fuente que agrega elxargs
comando.Tuve una respuesta vergonzosamente redonda aquí antes, pero la respuesta de Denis me recordó que me perdí lo más básico. Entonces, borré mi respuesta original. Pero como nadie ha dicho esto tan básico, creo que vale la pena ponerlo aquí.
La pregunta original es "Tengo un archivo de texto con una lista de nombres de archivos separados por espacios. Cómo puedo copiarlos en un directorio de destino". Al principio, esto puede parecer complicado o complicado, porque cree que de alguna manera tiene que extraer los elementos del archivo de una manera específica. Sin embargo, cuando el shell procesa una línea de comando, lo primero que hace es separar la lista de argumentos en tokens y (aquí está el bit que nadie ha dicho directamente) separa los tokens . (Las nuevas líneas también separan los tokens, razón por la cual la prueba de Doug Harris con una lista separada por una nueva línea tuvo el mismo resultado). Es decir, el shell espera y ya puede manejar una lista separada por espacios.
Entonces, todo lo que necesita hacer aquí es colocar la lista separada por espacios (que ya tiene) en el lugar correcto en su comando. Su comando es una variación de esto:
El único inconveniente es que desea obtener la lista de archivos 1 a # de su archivo de texto.
Como Dennis señala en su comentario, su intento original (
cp
cat list.txtnew_folder
) ya debería haber funcionado. ¿Por qué? Porque el comando internocat list.txt
es procesado primero por el shell y se expande enfile1 file2 file3...file#
, que es exactamente lo que el shell espera y quiere en esa parte del comando. Si no funcionó, (1) tenía un error tipográfico o (2) sus nombres de archivo eran algo extraños (tenían espacios u otros caracteres inusuales).La razón por la que todas las respuestas de Dennis funcionan es simplemente que proporcionan la lista necesaria de archivos para
cp
trabajar, colocando esa lista donde pertenece en el comando completo. Nuevamente, el comando en sí es esto en estructura:Es fácil ver cómo todo esto se combina en esta versión:
$()
hace que el shell ejecute el comando dentro de los paréntesis y luego sustituya su salida en ese punto en la línea más grande. Entonces el shell recorre la línea como un todo. Por cierto,$()
es una versión más moderna de lo que ya estaba haciendo con backticks (`). Siguiente:<
es un operador de redirección de archivos. Le dice al shell que descargue el contenido delist.txt
la entrada estándar. Como el$()
bit se procesa primero, esto es lo que sucede en etapas:cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
cp file1 file2 file3...file# new_folder
# substitute result of $(<list.txt) into the larger command
Obviamente, el paso 2 es simplemente el
cp
comando normal que deseabas.Me doy cuenta de que estoy golpeando mucho a este caballo (quizás muy muerto), pero creo que vale la pena hacerlo. Comprender exactamente cómo el shell procesa un comando puede ayudarlo a escribirlo mejor y simplificar mucho. También le mostrará dónde es probable que se oculten los problemas. En este caso, por ejemplo, mi primera pregunta debería haber sido sobre nombres de archivos divertidos o un posible error tipográfico. No se necesitaban acrobacias.
fuente
--parents
indicador. Puede hacerlo detallado-v
para obtener un registro de lo que se copió. Si desea mantener los permisos, necesita la bandera-a
o-p
. Es decir,cp --parents -av $(<list.txt) new_folder
. Todo esto supone que su lista de archivos son realmente todos los archivos, de lo contrario, es posible que también necesite-r
que se repita el indicador.--parents
bandera no existe allí. Su versión (derivada de BSD)cp
solo ofrece opciones cortas, no opciones largas al estilo GNU. Para un estilo BSDcp
, el indicador de copia recursiva es mayúscula-R
, no minúscula.