In a directory I have several sub-directories named as follow (the [1-9] means going from 1 to 9):


Each sub-directories contains a file (ascii) having exactly the same name as the directory. I did a mistake in the naming of several sub-directories (and their enclosed files):


How can I replace rier by river in the subdirectory and the enclosed file naming?


If you allow external programs you can use find and rename:

find . -type f -name '*_rier*' -exec rename 's/rier/river/g' {} \+
find . -type d -name '*_rier*' -exec rename 's/rier/river/g' {} \+

If you don't want to use external tools you can use

# rename directories
for f in *rier*; do
  mv -- "$f" "${f/rier/river}"

# rename files
for f in */*rier*; do
  mv -- "$f" "${f/rier/river}"

This first renames the directories and then the files.

  • The second option works. But the first one not, (I am curious) therefore, I would like to know if you have an idea about why the first option is not working? – steve Nov 13 '15 at 14:59
  • @steve It has to be done in two steps. Otherwise the path is wrong. Updated the answer. – Marco Nov 13 '15 at 15:27
  • shouldn't that be for f in *rier*/ ; do ... and for f in */*rier* ; do? or if you swap the order so the files are renamed before the dirs for f in *rier*/*rier* ; do ...? that'll eliminate attempts to rename files that don't need to be renamed. – cas Nov 13 '15 at 15:39
  • @cas Sure for f in * will act on all files and directories, not only the ones containing “rier”. So *rier* would be more precise but longer. I'll change it. – Marco Nov 13 '15 at 15:48
for file in $(find . -depth -name '*rier*'); do 
  mv $file $(echo $file | sed -e 's/rier/river/');
  • It does change the name of the directories, but not the name of the enclosed file and produce the error mv: cannot move DIRECTORY_NAME/FILE_NAME.txt to NEW_DIRECTORY_NAME/NEW_FILE_NAME.txt: no such file or directory – steve Nov 13 '15 at 14:32

With a for loop:

for d in AA_BB_CC_rier*; do
  [ -d "$d" ] && \
    mv -v -- "$d/$d" "$d/${d/rier/river}" && \
    mv -v -- "$d" "${d/rier/river}"

  • for loops trough all items starting with AA_BB_CC_rier.
  • [ -d "$d" ] checks if it's a directory.
  • mv renames the file in the directory.
  • The second call of mv renames the directory itself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.