1. Introduction

Renaming files based on attributes of those files enables us to organize data in an efficient manner. Sysadmins use this method for various kinds of archival and migration operations.

In this tutorial, we’ll explore several ways to rename files using shell commands. In particular, we’ll see examples of renaming a file based on several attributes:

We’ll use a Ubuntu 22.04 environment for running the examples.

2. Creation and Modification Date

To begin with, let’s find the creation date and modification date of a file and then rename the file based on those pieces of information.

2.1. File Dates

One way to print the date attributes of a file is the stat command:

$ stat --format "%W" disk.json
1689992509
$ stat --format "%Y" disk.json
1689992767

As illustrated above, we use the stat command to get the %W creation and %Y modification time of the files. Both times are in seconds since UNIX epoch.

So, let’s use the date command to convert this date format to a more human-readable string:

$ date --date=@1694498929 "+%Y_%m_%d-%H-%M-%S"
2023_09_12-11-38-49

Specifically, we use –date and the @ prefix to specify the seconds since the UNIX epoch, while +%Y_%m_%d-%H-%M-%S specifies the output format of the date:

  • %Y_%m_%d prints the year, month, and day with underscore separators
  • %H-%M-%S prints the hours, minutes, and seconds with dash separators

In summary, we explored the usage of the date and stat commands to get the file attributes.

2.2. Renaming the File

Finally, using all the above commands, we can rename files based on the creation date using the mv command:

$ mv ind.json ind_$(date --date=@$(stat --format "%W" ind.json) "+%Y_%m_%d-%H-%M-%S").json
$ mv disk.json ind_$(date --date=@$(stat --format "%W" disk.json) "+%Y_%m_%d-%H-%M-%S").json
$ ls
ind_2023_07_20-05-13-27.json disk_2023_07_22-07-51-49.json

As we can see above, the command performs several actions:

  • stat –format “%W” ind.json gets the UTC time as a UNIX timestamp
  • date –date=@$(stat –format “%W” ind.json) “+%Y_%m_%d-%H-%M-%S” converts the UTC time to human-readable format to form a filename
  • mv renames the file

Finally, we check the new names of both files are in effect via ls.

In summary, we used the creation date of a specified file, to generate a new file name and rename it.

3. Author of a PDF File

To get the author of a PDF file and rename the file based on that, we’ll use the pdfinfo command:

$ pdfinfo pdf_sample.pdf
Title: PDF Bookmark Sample
Author: Accelio Corporation
[...]

Here, we see the Author line. Let’s extract it via grep:

$ pdfinfo pdf_sample.pdf | grep "Author" 
Author: Accelio Corporation

Now, we remove the field name via awk:

$ pdfinfo pdf_sample.pdf | 
          grep "Author" | 
          awk -F':' -e '{ gsub(/^\s+|\s+$/,"",$2); print $2 }'
Accelio Corporation

Then, we remove spaces via tr to ensure compatibility of the name with more tools:

$ pdfinfo pdf_sample.pdf | 
          grep "Author" | 
          awk -F':' -e '{ gsub(/^\s+|\s+$/,"",$2); print $2 } |
          tr -s ' ' '_'
Accelio_Corporation

Finally, we rename the file by encapsulating the above via command substitution and check the result with ls:

$ mv pdf_sample.pdf $(
  pdfinfo pdf_sample.pdf |
    grep "Author" |
    awk -F':' -e '{ gsub(/^\s+|\s+$/,"",$2); print $2 }' |
    tr -s ' ' '_'
  )_pdf_sample.pdf
$ ls
Accelio_Corporation_pdf_sample.pdf

We can see above, that the final author extraction command performs several actions before renaming the file based on the author of the PDF file:

  • pdfinfo pdf_sample.pdf | grep “Author” extracts the Author line from the output of the pdfinfo command
  • awk -F’:’ -e ‘{ gsub(/^\s+|\s+$/,””,$2); print $2 }’ removes spaces from the prefix and suffix of the string
  • tr -s ‘ ‘ ‘_’ substitutes the intermediate spaces with _ underscore
  • mv renames the file
  • ls confirms the results

Finally, we check the new name of the file using ls.

To emphasize, we used a pipeline of commands to extract the author of the PDF file, create a file name, and finally, rename the file.

4. Owner of a Media File

To demonstrate, we use the exiftool command to get the name of a media file owner and rename the file based on that:

$ exiftool canon_400.jpg | head
ExifTool Version Number : 12.40
File Name : canon_400.jpg
Directory : .
File Size : 9.0 KiB
File Modification Date/Time : 2023:09:17 13:11:21+05:30
Owner Name : Jean-Pierre Grignon
[...]

Here, we see the Owner Name line. Again, we extract it with grep:

$ exiftool canon_400.jpg |
    grep "Owner"
Owner Name : Jean-Pierre Grignon

Next, we extract the name alone by splitting out the field via cut:

$ exiftool canon_400.jpg | grep "Owner" | cut -f2 -d ':'
 Jean-Pierre Grignon

Then, we remove any leading whitespace:

$ exiftool canon_400.jpg | 
            grep "Owner" | 
            cut -f2 -d ':' | 
            sed -e 's#^ \+##g'
Jean-Pierre Grignon

Similarly, let’s convert the spaces to underscores:

$ exiftool canon_400.jpg | 
            grep "Owner" | 
            cut -f2 -d ':' | 
            sed -e 's#^ \+##g' | 
            tr -s ' ' '_'
Jean-Pierre_Grignon

Finally, we rename the file and verify:

$ mv canon_400.jpg $(
  exiftool canon_400.jpg |
    grep "Owner" |
    cut -f2 -d':' |
    sed -e 's#^ \+##g' |
    tr -s ' ' '_'
  )_canon_400.jpg
$ ls
Jean-Pierre_Grignon_canon_400.jpg

In general, we create a pipeline of commands to rename the file based on the owner of the media file:

  • exiftool pdf_sample.pdf | grep “Owner” extracts the Owner line from the output of the exiftool command
  • cut -f2 -d’:’ extracts the second field from the line, using: colon as the field separator
  • sed -e ‘s#^ \+##g’ trims spaces from the beginning and end of the string
  • tr -s ‘ ‘ ‘_’ substitutes the intermediate spaces with _ underscore
  • mv renames the file
  • ls shows the new file name

In particular, we combined the commands cut, sed, and tr to generate the file name. Finally, we applied the name with mv.

5. Copying a Collection of Files

We’ll use the find command to get a collection of files based on criteria and copy the files:

$ find /var/log/cups/ -name "*.gz" -printf "%p\n"
/var/log/cups/error_log.2.gz 
/var/log/cups/error_log.6.gz
[...]

Now, let’s check our script that leverages this command:

$ cat rename.sh
#!/usr/bin/env bash 
for src in $(find /var/log/cups/ -name "*.gz" -printf "%p\n"); 
do 
    dst=$(basename $src)
    cp $src $(date --date=@$(stat --format "%W" $src) "+%Y_%m_%d-%H-%M-%S")_$dst
done
$ ./rename.sh
$ ls -1
2023_09_28-10-16-40_error_log.2.gz
2023_07_20-05-02-23_error_log.6.gz

To be clear, the script uses a sequence of Bash commands to rename the files based on a search criterion using the find command:

  • find /var/log/cups/ finds the files in the given directory
  • -name “*.gz” searches the files which match the pattern “*.gz”
  • -printf “%p\n” prints each of the results on a separate line
  • basename $src extracts the filename from the directory name
  • sed -e ‘s#^ \+##g’ trims spaces from the beginning and end of the string
  • $(date –date=@$(stat –format “%W” $src) “+%Y_%m_%d-%H-%M-%S”)_$dst generates the destination filename based on the date
  • cp copies the file

In general, we used a pattern to search the files and copied them to a different location. To sum up, this process can be helpful for taking backups or building archives.

6. Conclusion

In this article, we learned a few ways to rename a file based on the attributes of that file.

Firstly, we used the combined stat and date commands to get the file attributes. Secondly, we generated the new filename based on the attributes. Thirdly, we explored using pdfinfo command to extract the author of the PDF file. Similarly, we saw the usage of exiftool to retrieve metadata from a media file and apply it to the name of that file. Finally, we saw advanced usage of a pipeline of Bash commands for generating the file name.

We also explored combining all the above ideas into a script and renaming a collection of files based on their modification dates.