I have a folder parentdir with many directories like this:

$ tree parentdir/subdir_1

├── important.txt
├── important_001.txt
├── important_002.log
├── important_007.bmp
├── something
├── else.mp3
├── nothing.000
└── ignore.me

What I want is to move all files with a name starting with important to the parent directory parentdir and renaming them by prefixing each file name with the name of the subdirectory they came from.

For example, parentdir/subdir_1/important_001.txt should be moved/renamed to parentdir/subdir_1-important_001.txt.

How can I most easily perform this bulk move/rename operation on a huge directory?


In parentdir you could use

for f in ./*/important*; do rename -n 's#\./([^/]+)/(.*)#$1-$2#' "$f" ; done

Remove -n after testing to actually move and rename


  • s#old#new# replace old with new
  • \./([^/]+)/(.*) match literal ./ then save some characters other than /, then match /, then save the rest
  • $1-$2 the two saved patterns separated by -

Ditching the path separator moves the files to parentdir by force

Afterthought: more simply in this case you could just use s#/#-# to replace / with -, omitting ./ from the start

for f in */important*; do rename -n 's#/#-#' "$f" ; done
  • A wildcard pattern in a really huge directory will overflow the command line buffer -- better to feed the names into a loop one at a time, but since the answer was accepted, I guess no overflow occurred. – ubfan1 Jan 15 '17 at 5:56

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