Tengo el siguiente script, que normalmente uso cuando obtengo un montón de archivos que necesitan ser renombrados al nombre del directorio que los contiene.
El problema ahora es que necesito cambiar el nombre del archivo al directorio dos niveles más arriba. ¿Cómo puedo obtener el directorio de abuelos para que esto funcione?
Con lo siguiente obtengo errores como este ejemplo: "mv: no se puede mover ./48711/zoom/zoom.jpg a ./48711/zoom/./48711/zoom.jpg : No existe tal archivo o directorio". Esto se ejecuta en CentOS 5.6.
Quiero que el archivo final se llame: 48711.jpg
#!/bin/bash function dirnametofilename() { for f in $*; do bn=$(basename "$f") ext="${bn##*.}" filepath=$(dirname "$f") dirname=$(basename "$filepath") mv "$f" "$filepath/$dirname.$ext" done } export -f dirnametofilename find . -name "*.jpg" -exec bash -c 'dirnametofilename "{}"' \; find .Otro método podría ser utilizar
(cd ../../; pwd) Si esto se ejecutara en cualquier ruta de nivel superior como / , /usr/ o /usr/share/ , obtendría un directorio válido de / , pero cuando profundice un nivel más, comenzará a ver los resultados: /usr/share/man/ devolvería /usr , /my/super/deep/path/is/awesome/ devolvería /my/super/deep/path , y así sucesivamente.
También podría almacenar esto en una variable:
GRANDDADDY="$(cd ../../; pwd)"y luego utilícelo para el resto de su script.
Asumiendo que la ruta del archivo no termina en / , lo que no debería hacer si usa dirname , puede hacerlo
Parent = "${filepath%/*}" Grandparent = "${filepath%/*/*}"Entonces haz algo como esto
[[ "${filepath%/*/*}" == "" ]] && echo "Path isn't long enough" || echo "${filepath%/*/*}" Además, es probable que esto no funcione si está utilizando rutas relativas (como find . ). En cuyo caso querrás usar
filepath=$(dirname "$f") filepath=$(readlink -f "$filepath")en vez de
filepath=$(dirname "$f")Además, nunca elimina la extensión, por lo que no hay razón para obtenerla del archivo y luego agregarla nuevamente.
Nota:
* Esta respuesta resuelve el problema específico del OP , en cuyo contexto "directorio principal" significa: el directorio principal del directorio que contiene un archivo (es la ruta principal desde la perspectiva del archivo ).
* Por el contrario, dado el título genérico de la pregunta, otras respuestas aquí se enfocan (solo) en obtener el directorio principal de un directorio; la respuesta sucinta a la pregunta genérica es : grandParentDir=$(cd ../..; printf %s "$PWD") para obtener la ruta completa y grandParentDirName=$(cd ../..; basename -- "$PWD") para obtener el directorio. solo nombre
Prueba lo siguiente:
find . -name '*.jpg' \ -execdir bash -c \ 'old="$1"; new="$(cd ..; basename -- "$PWD").${old##*.}"; echo mv "$old" "$new"' - {} \; Nota: echo se antepuso a mv para estar seguro; elimínelo para realizar el cambio de nombre real.
-execdir ..\; ejecuta el comando especificado en el directorio específico que contiene un archivo coincidente dado y expande {} al nombre de archivo de cada uno.
bash -c se usa para ejecutar un pequeño script ad-hoc:
$(cd ..; basename -- "$PWD") determina el nombre del directorio principal del directorio que contiene el archivo, que es la ruta principal desde la perspectiva del archivo .
${old##*.} es una expansión de parámetros de Bash que devuelve el sufijo (extensión) del nombre del archivo de entrada.
Tenga en cuenta cómo {} , el nombre de archivo en cuestión, se pasa como el segundo argumento del comando para vincularlo a $1 , porque bash -c usa el primero para establecer $0 (que se establece en un valor ficticio _ aquí).
Tenga en cuenta que cada archivo simplemente se renombra , es decir, permanece en su directorio original .
Advertencia :