1 votes

Utilisation de find et sed pour renommer plusieurs sous-dossiers

Ce que j'essaie de faire, c'est de renommer des dossiers qui se trouvent n'importe où dans l'arbre actuel, et pas nécessairement directement dans le répertoire de travail. Ce que j'ai besoin de faire est :

  • "A 1" devient "A 01"
  • "A 2" devient "A 02"
  • "A 09" est ignoré

Je me suis retrouvé avec ça :

find . -type d -regex '.*A [0-9]$' -execdir mv "{}" "$(echo '{}' | sed 's_[0-9]_0&_')" \;

Afin de tester cela, j'ai réduit un peu la complexité :

find . -type d -regex '.*A [0-9]$' -execdir echo "$(echo '{}' | sed 's_[0-9]_0&_')" \;

find liste tous les dossiers que je veux, mais le modèle en sed ne semble pas trouver de correspondance dans les noms de dossiers. Il fonctionne s'il est exécuté seul, donc je suppose qu'il y a un problème avec les caractères qui doivent être échappés.

1voto

Peter.O Points 2933

Mise à jour : Ajout d'une version qui peut gérer tous les caractères valides des noms de fichiers, à l'exception des caractères suivants \x01 qui est utilisé comme délimiteur de sed.... J'ai utilisé A.* comme le modèle dans le actualisé des exemples, parce que je testais pour A"' . Bien sûr, il suffit de changer ce que vous voulez.

findx="\(.*/\)\(A.* \)\([0-9]\)$"
replx="&\x00\1\20\3\x00"; I=$'\x01'
find . -depth -type d -regex "$findx" | 
  sed -n "s$I$findx$I$replx$I p" |
    tr -d '\n' | 
      xargs --verbose -0n2 mv 

Voici un exemple, utilisant perl au lieu de sed .
Notez que de perl expressions reguales PCRE ne sont pas tout à fait les mêmes que posix-extended ERE tel qu'utilisé par find dans cet exemple. Cependant, ils ont suffisamment en commun pour que le même modèle regex puisse être utilisé dans ce cas.

export findx='(.*/)(A.* )([0-9])$'
find . -depth -type d -regextype posix-extended -regex "$findx" |
  perl -l000pe 's/$ENV{'findx'}/$_\000$1${2}0$3/' |
    xargs --verbose -0n2 mv 

Ces prochaines versions ne peuvent pas gérer les guillemets simples ' dans les noms de fichiers.

Utilisation de modèles de regex standard

regex='\(.*/\)\(A \)\([0-9]\)$'
find . -depth -type d -regex "$regex" |
  sed -n "s|$regex|'&' '\1\20\3'|p" |
    xargs --verbose -n2 mv 

Pour utiliser des paternes de regex étendues

regex='(.*/)(A )([0-9])$'
find . -depth -regextype posix-extended -type d -regex "$regex" |
  sed -nr "s|$regex|'&' '\1\20\3'|p" |
    xargs --verbose -n2 mv 

En -depth est nécessaire pour que l'option plus profondément les répertoires imbriqués sont renommés avant que tout répertoire parent soit renommé.

Notez que le script ne teste pas si un répertoire existe déjà avec le même nom que le nouveau nom prévu.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X