I am trying to rename the files and directories using a text file separated by space.

The files.txt looks like this:

dir1-1 dir1_1
dir2-1 dir223_1

My command is as follows:

xargs -r -a **files.txt** -L1 mv

The files look like this (in directory 1):

dir1-1.txt dir1-1.gzip dir1-1-something.text

The output for the files should look like this (in the dir1-1):

dir1_1.txt dir1_1.gzip dir1_1-something.text

The files in directory (dir2) looks like this:

dir2-1.py dir2-1.txt dir2-1.text

The output should look like this:

dir223_1.py dir223_1.txt dir223_1.text

This command can rename only folders from dir1-1 to dir1_1 and dir2-1to dir223_1so on but it doesn't rename the files in the subdirectories. The files in the corresponding directories also have these prefix of these directories. (like dir1-1.txt dir1-1.gzip dir1-1.csv)

It will be somewhat similar like: Script for renaming files using text file containing alternate file names

Looking forward for the assistance.

  • xargs command work only on file lines. So mv is only called on those values. Do you put in your question an example of file names and directories/sub-directories structure and of course an example of what do you expect. Thanks Sep 12, 2021 at 13:13
  • Use the perl rename utility. There are many questions with detailed answers on how to use it here on this site. It can handle any kind of renaming task, from simple sed-like filename transformations (s/old/new/) to a a complex script using any valid perl code.
    – cas
    Sep 12, 2021 at 13:30
  • I have used rename utility. But I am unable to use it via text file. I have used multiple options to rename the file using the extensions, specific pattern in the file name, replacing specific characters, finding the names in subdirectories and moving them but none of these condition apply to my query. (using a text file with an old name and new name in the file)
    – soosa
    Sep 12, 2021 at 13:43
  • You can do this with rename, using perl's open() function to open the files.txt file for read, then iterate over lines in the file and split each line on white-space....but for a job like this, it's probably easier to just write a perl script without using the perl rename tool. or a bash script as in my answer below.
    – cas
    Sep 12, 2021 at 17:08

1 Answer 1


There's lots of ways of doing this, but here's a very simple and straight-forward example of one way to do this:

$ cat files.txt 
dir1-1 dir1_1
dir2-1 dir223_1

$ cat rename.sh

# make some dirs and files to test with:
d='dir1-1'; mkdir "$d"; for ext in .txt .gzip -something.txt; do touch "$d/$d$ext" ; done
d='dir2-1'; mkdir "$d"; for ext in .py .txt .text; do touch "$d/$d$ext" ; done

# now rename them:
while read -r old new ; do
  # rename the directory too
  mv -v "$old" "$new"

  # and rename the files
  if [ -d "$new" ] ; then
    for f in "$new/"* ; do
      mv -v "$f" "$(printf "%s" "$f" | sed -e "s/$old/$new/g")"
done < files.txt

$ chmod +x rename.sh

$ ./rename.sh 
renamed 'dir1-1' -> 'dir1_1'
renamed 'dir1_1/dir1-1.gzip' -> 'dir1_1/dir1_1.gzip'
renamed 'dir1_1/dir1-1-something.txt' -> 'dir1_1/dir1_1-something.txt'
renamed 'dir1_1/dir1-1.txt' -> 'dir1_1/dir1_1.txt'

renamed 'dir2-1' -> 'dir223_1'
renamed 'dir223_1/dir2-1.py' -> 'dir223_1/dir223_1.py'
renamed 'dir223_1/dir2-1.text' -> 'dir223_1/dir223_1.text'
renamed 'dir223_1/dir2-1.txt' -> 'dir223_1/dir223_1.txt'

NOTE: Because your files.txt has a single space separating the old and the new patterns for file and directory name, and also because I'm using read with the default IFS setting of $' \t\n' (space, tab, or newline), the following script will work with any filename patterns that don't have those characters (or a / because that's being used as the delimiter in sed) in them.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .