Cambie el nombre de archivos y directorios de forma recursiva con Bash en macOS

CorePress2024-01-24  11

Estoy escribiendo un script que realizará algunas acciones, y una de esas acciones es encontrar todas las apariciones de una cadena tanto en nombres de archivos como en nombres de directorios, y reemplazarlas con otra cadena.

Tengo esto hasta ahora

find . -name "*foo*" -type f -depth | while read file; do
    newpath=${file//foo/bar}
    mv "$file" "$newpath"
done

Esto funciona bien siempre y cuando la ruta al archivo no contenga también foo, pero eso no está garantizado.

Siento que la forma de abordar esto es SÓLO cambiar los nombres de los archivos primero, luego regresar y cambiar los nombres de los directorios, pero incluso entonces, si tiene una estructura que tiene más de un directorio con foo en él, no funcionará correctamente.

¿Hay alguna manera de hacer esto con las herramientas integradas de macOS? (Digo integrado, porque este script se distribuirá a otras personas de nuestra organización y no puede depender de ningún paquete).kages a instalar).

¿Podrías separar el nombre de ruta del nombre de archivo y luego hacer la sustitución y luego reconstruirlos/unirlos antes de cambiar el nombre?

- Jetchisel

26/03/2021 a las 16:35



------------------------------------

Separando el nombre_ruta del nombre_archivo, algo así como.

#!/usr/bin/env bash

while read -r file; do
  path_name="${file%/*}"; printf 'Path is %s\n' "$path_name"
  file_name="${file#"$path_name"}"; printf 'Filename is %s\n' "$file_name"
  newpath="$path_name${file_name//foo/bar}"
  echo mv -v "$file" "$newpath"
done < <(find . -name "*foo*" -type f)

Echa un vistazo también al nombre base y al nombre de directorio.

El printf está ahí para scómo cuál es la ruta y el nombre del archivo.

El script simplemente reemplaza foo por bar desde el nombre_archivo. También se puede hacer con el nombre_ruta, solo use la misma sintaxis.

newpath="${path_name//bar/more}${file_name//foo/bar}"

Así que cambie el nombre de nombre_ruta y nombre_archivo.

O cambiar el nombre de la ruta y luego el nombre del archivo como si fuera tu idea también es una opción.

path_name="${file%/*}"
file_name="${file#"$path_name"}"
new_pathname="${path_name//bar/more}"

mv -v "$path_name" "$new_pathname"

new_filename="${file_name//foo/bar}"

mv -v "${new_pathname%/*}$file_name" "$new_pathname$new_filename"

No se utilizan herramientas/utilidades externas adicionales, excepto las que utiliza su script.

Elimine el eco si está satisfecho con el resultado/salida.

4

Le daré unatiro.

-RPK

26/03/2021 a las 16:52

Esto funciona para los nombres de los archivos, pero no puede cambiar las rutas del directorio al mismo tiempo que el nombre del archivo, ya que el directorio no existe.

-RPK

26/03/2021 a las 17:50

Sí, el directorio debe existir antes de poder cambiarle el nombre.

- Jetchisel

26/03/2021 a las 17:51

1

Terminé eligiendo algo muy similar a lo que tienes aquí y funcionó. Gracias por la ayuda.

-RPK

26/03/2021 a las 19:55



------------------------------------

Puedes usar -execdir para ejecutar un comando solo en el nombre del archivo (nombre base) en el directorio correspondiente:

find . -depth -name '*foo*' -execdir bash -c 'mv -- "" "${1//foo/bar}"' _ {} \;

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare