Necesito almacenar el nombre de cada archivo contenido en un directorio con un script bash y procesarlo de alguna manera:
drwxrwxr-x 5 matteorr matteorr 4096 Jan 10 17:37 Cluster drwxr-xr-x 2 matteorr matteorr 4096 Jan 19 10:43 Desktop drwxrwxr-x 9 matteorr matteorr 4096 Jan 20 10:01 Developer drwxr-xr-x 11 matteorr matteorr 4096 Dec 20 13:55 Documents drwxr-xr-x 2 matteorr matteorr 12288 Jan 20 13:44 Downloads drwx------ 11 matteorr matteorr 4096 Jan 20 14:01 Dropbox drwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 Music drwxr-xr-x 2 matteorr matteorr 4096 Jan 19 22:12 Pictures drwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 Public drwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 Templates drwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 Videos con el siguiente comando puedo dividir el resultado de ls -l entre todos los espacios y luego acceder al último elemento, que contiene el nombre:
ls -l | awk '{split($0,array," ")} END{print array[9]}' Sin embargo, solo devuelve la última línea (es decir, Videos ), por lo que necesito iterarlo sobre todas las líneas devueltas por el ls -l .
PARTE AÑADIDA
Para ser un poco más específico en lo que tengo que hacer:
Para todos los archivos contenidos en un directorio, si es un archivo, no haré nada, si es un directorio, debo agregar el nombre del directorio a todos los archivos que contiene.
Entonces supongamos que el directorio Videos tiene los archivos:
-rwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 video1.mpeg -rwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 Video2.wmvNecesito cambiarles el nombre de la siguiente manera:
-rwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 video1_Videos.mpeg -rwxr-xr-x 2 matteorr matteorr 4096 Oct 18 18:43 Video2_Videos.wmvUna mejor manera sería usar bash globbing
Solo listando todos los archivos
echo *O hacer algo con ellos.
for file in *; do echo "$file" # or do something else doneO recursivamente con bash 4+
shopt -s globstar for file in **/*; do echo "$file" # or do something else doneActualizar para obtener el nombre del directorio y agregarlo a todos los archivos dentro de él
Reemplace mv con un echo para probar lo que hace. También tenga en cuenta que ${file##*.} asume que la extensión es todo después del último punto, por lo que si tuviera un archivo como file.tar.gz en el directorio on , debajo lo convertiría en file.tar_on.gz . Hasta donde yo sé, no hay una manera fácil de manejar este problema, aunque podría omitir archivos con múltiples . si tu quieres)
#!/bin/bash d="/some/dir/to/do/this/on" name=${d##*/} #name=on for file in "$d"/*; do extension=${file##*.} filename=${file%.*} filename=${filename##*/} [[ -f $file ]] && mv "$file" "$d/${filename}_${name}.$extension" donep.ej
> ls /some/dir/to/do/this/on video1.mpeg Video2.wmv > ./abovescript > ls /some/dir/to/do/this/on video1_on.mpeg Video2_on.wmvExplicación
En bash puedes hacer esto
${parameter#word} Elimina el prefijo coincidente más corto${parameter##word} Elimina el prefijo coincidente más largo${parameter%word} Elimina el sufijo coincidente más corto${parameter%%word} Elimina el sufijo coincidente más largo Para eliminar todo lo que sea ( * ) antes e incluido el último punto, lo hice a continuación
extension=${file##*.} Para eliminar todo, incluido y desde el último punto, lo hice a continuación (piense en la coincidencia más corta aquí de derecha a izquierda, por ejemplo, * busca cualquier texto que no sea de punto de derecha a izquierda, luego, cuando encuentra un punto, elimina toda esa sección )
filename=${file%.*} Para eliminar todo hasta el último / incluido, lo hice a continuación.
filename=${filename##*/}Algunas otras notas:
"$d/${filename}_${name}.$extension" Las variables pueden tener _ , así que cambié la sintaxis de un par de variables aquí para que funcione"$d"/* expande a todos los archivos de cualquier tipo (regular, dir, enlace simbólico, etc.) directamente en "$d"Lo que está mal con
ls > myfile.txt Esto solo enumerará los nombres de los archivos (nada más) y los enviará a myfile.txt
Si quieres ir por la ruta awk , solo hazlo
ls -l | awk '{print $9}' La acción predeterminada de awk es dividir los campos en el espacio, y esto imprime el noveno campo para cada línea...
Si desea hacer otras cosas con los nombres de los archivos, simplemente puede extender su secuencia de comandos awk. Por ejemplo, se podría crear una matriz con estos nombres de archivo con
ls -l | awk '{a[NR]=$9}' y puede usar esta matriz (llamada a ) en el procesamiento posterior. Si el procesamiento requiere algo más que awk (por los comentarios, creo que sí), estaría mejor con algo que se parezca a
#!/bin/bash for f in $1"/"* do if [ -d "$f" ] ; then ./listdir $f else echo $f fi done Guarde esto como listdir en su directorio actual y listo.
./listdir .Enumerará el directorio completo, recursivamente hacia abajo (con la ruta relativa completa adjunta) según sea necesario.
Si desea que esto esté disponible "desde cualquier lugar" (después de todo, es un comando bastante útil), lo colocaría en algún lugar de su camino (y haría un comando de "repetición" para que sea "conocido"); entonces no necesita el ./ al comienzo del comando.
¡Buena pregunta! Me alegro de que hayas preguntado. Analizar la salida de ls rara vez es lo correcto. Hay innumerables formas de procesar una lista de archivos. Depende de lo que quieras hacer con ellos.
Estos son algunos ejemplos de cosas que puede hacer. He usado touch como un comando de ejemplo. Reemplace eso con cualquier comando o comandos que desee hacer.
Para ejecutar un comando en varios archivos, a menudo puede simplemente pasar todos los archivos en la línea de comandos.
touch /var/myapp/*Para recorrer los archivos en el directorio actual:
for file in *; do touch "$file" donePara recorrer archivos en otro directorio:
for file in /some/dir/*; do touch "$file" done Para cambiar el nombre de los archivos llamados *.txt a '*.bak', tanto aquí como en los subdirectorios:
find . -name '*.txt' -exec mv {} {}.bak \;Para eliminar archivos JPEG en el directorio de inicio de Bob (maldito seas Bob y tus ojos errantes):
find ~bob/ -name '*.jpg' -deletePara recorrer los archivos recursivamente y hacerles cosas complicadas:
find /dir/to/search -print0 | while read -d $'\0' file; do echo "$file" touch "$file" if [[ -L $file ]]; then # $file is a symlink, do something special fi done