Changing date format in filenames in Linux [Solved]

Evenin’ all. (forum members under about sixty will definitely not get the reference).

I’ve got a lot of files in the format dd_mm_yyyy.mp3 which I’d like to amend to yyyy_mm_dd.mp3.

I’m sure I once found a way to do that using the command line, but I can’t find it now.

Any help appreciated.

Mind how you go. (see above).

Hi Mike.

The “touch” command can be used to change the date format of a file, but it looks like you want to change the file names.
There are bulk-file-renaming methods such as Thunar file manager, and suggestions on the internet but are either very complicated or not really want you want.
I suggest that the simplest method is to write a short script to do it.

Here’s my example to try in your script directory:

#!/bin/bash

> dd-mm-yyyy.mp3

for file in $(ls -1 *.mp3); do 
 day=$(echo $file | cut -d "-" -f 1)
 month=$(echo $file | cut -d "-" -f 2)
 year=$(echo $file | cut -d "-" -f 3 | cut -d "." -f 1)
 suffix=$(echo $file | cut -d "." -f 2)
 new_file=$year"-"$month"-"$day"."$suffix
 echo "Old file: $file new file: $new_file"
 mv $file $new_file
done

This will change all files in one go.
Hope that helps a bit
Keith

'Evening all? With a blue light.

Thanks Keith, I appreciate you taking the time.

Yes, I want to reverse the date format in the filenames in order to be able to sort them accurately. I tried Thunar and the internet without success.

I’m not yet up on scripting, although I will try to be eventually. I get the general idea of what your script is doing (old programmers never die) and will definitely give it a go. I’m sure it will work.

Three questions though.

How do I identify my script directory?
How do I run the script?
How do I specify where the files are?

Obviously I’ll make a backup before I start…

Mike

and yes, with a blue light.

Hi Mike.
No problem: I will reply tomorrow. Well, today now.

Keith

Hi,
If your feeling adventurous and are willing to stray beyond the shell, how about;

#!/usr/bin/env python3 
 
from sys import argv 
from shutil import move 
argv.pop(0) 
 
try: 
    for name in argv: 
        path = name.split("/") 
        file = path.pop() 
        parts = file.replace('.','-').split('-') 
        ext = parts.pop() 
        parts.reverse() 
        path.append('-'.join(parts) + '.' + ext) 
        rename = '/'.join(path) 
        move(name, rename) 
        print(f'renamed "{name}" to "{rename}"') 
except Exception as e: 
    print(f'Failed: {str(e)}')

If you paste this into “movemyfile.py” and then do “chmod a+x movemyfile.py” you should then have something that will move a bunch of files from the command line, or that can be using with “find”.

$ find . -name "*.mp3" -exec ./movemyfile.py {} \;

renamed "./12-03-2012.mp3" to "./2012-03-12.mp3"
renamed "./tmp/yyyy-mm-dd.mp3" to "./tmp/dd-mm-yyyy.mp3"

$ find . -name "*.mp3" -exec ./movemyfile.py {} \;

renamed "./2012-03-12.mp3" to "./12-03-2012.mp3"
renamed "./tmp/dd-mm-yyyy.mp3" to "./tmp/yyyy-mm-dd.mp3"

$ ./movemyfile.py 12-03-2012.mp3  
renamed "12-03-2012.mp3" to "2012-03-12.mp3"

So this can process an entire directory tree via one line … also it’s “reversible” so if you run it again it should put it back the way it was … I stress “should”, backup first … :slight_smile:

Note; there’s not much error checking, if you run it over “other” files it will break badly!
(Comment out the “move” if you just want it to print what it “would” do …)

@Mad Penguin
Speaking for for myself; using Python adds another layer of understanding to be mastered and in this particular example there is more typing! In addition Mike asks some pertinent questions that need to be answered before being able to execute the script.

@Mike
MP’s solution is very elegant if longer than my suggestion. You can choose whichever method appeals to you most but I still need to answer your particular questions and add some critical details that MP doesn’t address.
I have a feeling that there will be many readers following this post with interest as scripting can seem a very mysterious art so, if you don’t mind, I’ll run through the process from the basics before addressing the script itself. As scripting questions come up quite a lot, I shall discuss with The Management the possibility of adding a Board about this very subject.
We shall do three things:

[ol]

  • Tell the computer where all our script can be found
  • Write our script
  • Make our script executable.
    [/ol]

First of all I recommend that you dedicate a directory to all house all your scripts. In a fresh terminal, enter

mkdir scripts

Scripts are invoked by simply typing its name in the command line. The computer then has to go off and look for it. Rather than have to search the whole machine for it, scripts are conventionally kept in just a few places that are kept as a colon-separated list in an “environment variable” called PATH. We can add our own “place” to this list. If you type the following code into a terminal it will show the current list of these places.

echo $PATH

Editing this list directly is not a good idea (don’t ask!) but Linux has provided a foolproof way of doing it. In your Home directory is a hidden file .profile which can be edited to add our new directory. Start your favourite text editor (e.g. gedit in Ubuntu) and enter Ctrl+h to display hidden files. Select .profile.
To the end of this file add:

# set PATH so it includes user's script directory if it exists
if [ -d "$HOME/scripts" ] ; then
    PATH="$PATH:$HOME/scripts" export PATH
fi

Save and close the file. Now if you display the PATH variable as before you will see that your script directory has been added to the end.

Let me know that all is well so far, and which script you want to use, before we go on.
Keith

Thank you both very much for your time.

With respect, MP, I think I’ll keep it as simple as possible and avoid Python for the moment. As Keith says, it’s another learning curve…

Keith, I’ve installed Gedit but when I run it and type ctrl+h I just get the search and replace dialogue. No mention of hidden files…

My apologies, MIke. I missed out a bit.

After starting Gedit, click on the “Open” tab at the top left of the window. This will display a file-manager-like list of files in your home directory.
Now you click Ctrl+h and you will see lots of extra files prefixed with a “.” - these are the “hidden” files. You can toggle Ctrl+h to show/hide hidden files.
Scroll down until you see .profile and select that one, then either double-click on it or click on the “Open” button at top right of the window. The file will now be displayed.
Add the extra lines to the end of the file, save and close. You don’t need to reboot for the changes to take effect.

I’ve attached an improved bit of code for your script. Let me know when you’ve installed it in your scripts directory and we’re ready to rock & roll.
By the way: how did the PATH change go?

Keith

Hello Keith.

I’ve found .profile using gedit, but now I’m getting a permissions error when trying to open it. So I tried opening gedit from the terminal using ‘sudo gedit’. I’m asked for my password, then I get the message "mkdir: cannot create directory ‘/run/user/0’: Permission denied
No protocol specified

(gedit:6152): Gtk-WARNING **: 20:09:45.714: cannot open display: :0.0

Not sure what you mean by 'how did the PATH change go?". I thought that’s what I’m trying to do by editing .profile…

Mike,
Yes, you are right - I am confusing both of us. So one step at a time.
I have just opened .profile into gedit by simply double-clicking on it in the file manager. This means that the file is not write protected in my Ubuntu. I believe you are using MX so things might be different, but the error you received is weird.

In a terminal enter

ls -l .profile

If there is no “w” amongst the first few letters of the response then the file is write-protected and we need to un-protect it.
If there is no “w” then please try double-clicking on .profile in your file manager to see if that opens it in gedit. If it does, then add the text that I suggested earlier, then close the file.

Let me know how that goes - I’m in all night and all day tomorrow.
Keith

Keith,

Yes there’s an rw in the string.

Mike

OK, so the file does have write access and there is no reason why we can’t modify it.
I mentioned that I could open the file in gedit by simply double-clicking on it in the file manager. Try that.
If that doesn’t work then:

[ol]

  • start gedit
  • click on “Open”, which will open the Home directory
  • scroll down to .profile and double-click on it
    [/ol]

If either of these methods works, then add to the end of the file the text that I showed earlier:

# set PATH so it includes user's script directory if it exists
if [ -d "$HOME/scripts" ] ; then
    PATH="$PATH:$HOME/scripts" export PATH
fi

If you still can’t edit the file, please paste the screen output here.
Keith

Keith, I’m confused. I thought you said if there was a ‘w’ the file was write protected…

If I double click .profile in Thunar it opens a file in mousepad called home/m/.profile. I’m guessing/hoping that just means mousepad is my preferred editor and I can add the new text using mousepad?

I just tried that, and echo $path hasn’t changed it’s output…

Update. Just did a restart and now scripts appears in the output from echo $path.

Update2. I just tried to copy and paste your script into the scripts folder but it won’t let me! Nothing happens.

Update3. Ok. Just created a file in scripts, called script1. Opened script1 and pasted your code into it. Made a copy of the folder I want to change the filenames in. Now baffled as to how to invoke script1…

Ah, so restart is necessary in MX - OK.

Update2. I just tried to copy and paste your script into the scripts folder but it won't let me! Nothing happens.

The script has to be pasted into a text document. So:

  1. copy this script:
#!/bin/bash
> dd-mm-yyyy.mp3
for file in $(ls -1 *.mp3); do 
 day=$(echo $file | cut -d "-" -f 1)
 month=$(echo $file | cut -d "-" -f 2)
 year=$(echo $file | cut -d "-" -f 3 | cut -d "." -f 1)
 suffix=$(echo $file | cut -d "." -f 2)
 new_file=$year"-"$month"-"$day"."$suffix
 echo "Old file: $file new file: $new_file"
 mv $file $new_file
done
  1. start your script application (mousepad?)
  2. paste the script text
  3. save as “name-reformat” in your scripts directory

Now, just to check: please post everything from these commands (including the commands):

ls -l .profile scripts

echo $PATH

If all is well, the next task will be to make the script executable. Nearly there!
Keith

Thanks Keith,

It’s xubuntu by the way.

Here are the results. Sorry, it’s a screenshot. Copy and paste from the terminal just results in a blinding white background which makes it unreadable!
http://home/m/Screenshot_2023-04-3030_22-20-17.png

http://home/m/Desktop/screenshot

m@m-xubuntu:~$ ls -l .profile scripts
-rw-r–r-- 1 m m 1050 Apr 30 21:00 .profile

scripts:
total 4
-rw-rw-r-- 1 m m 345 Apr 30 22:17 script1.txt
m@m-xubuntu:~$ echo $PATH
/home/m/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/m/.local/bin:/home/m/scripts
m@m-xubuntu:~$ ^C
m@m-xubuntu:~$

Excellent.
I notice that you have called your script script1.txt. This is not a good idea for two reasons:

[ol]

  • when you have accumulated lots of scripts with similar names you won’t remember what they all do - they need to have memorable names
  • although the script is a text file it doesn’t need the .txt extension. (in fact Linux doesn’t need any file extensions)
    [/ol]

So I recommend that you change the name to something like my suggestion: name-reformat. That will always tell you what it does, and you can change it if you prefer something else.
Start a terminal session then:

cd scripts

then change the name:

mv script1.txt name-reformat

then change the permissions to make the script executable:

chmod +x name-reformat

then check:

ls -l name-reformat

Please copy and paste all the output.
The next bit will demonstrate the script to check that it works as expected, before actually working on your mp3 files.

Keith

Hello Keith,

Here’s the output, including a couple of typos I included just for fun!

m@m-xubuntu:~$ cd scripts
m@m-xubuntu:~/scripts$ mv script1.txt nama-reformat
m@m-xubuntu:~/scripts$ chmod +x mane-reformat
chmod: cannot access ‘mane-reformat’: No such file or directory
m@m-xubuntu:~/scripts$ chmod +x name-reformat
chmod: cannot access ‘name-reformat’: No such file or directory
m@m-xubuntu:~/scripts$ mv script1.txt name-reformat
mv: cannot stat ‘script1.txt’: No such file or directory
m@m-xubuntu:~/scripts$ mv nama-reformat name-reformat
m@m-xubuntu:~/scripts$ chmod +x name-reformat
m@m-xubuntu:~/scripts$

I haven’t run the ls command yet because it doesn’t specify a directory so I assume it will act on all directories. The problem with that is that I have other directories with similarly named files I don’t want to change at the moment - including the backup directory I made earlier in case anything goes wrong.
I know ls doesn’t change anything, but at some point I’ll need to make this folder-specific…

Mike

Hello Mike.

Just a few errors! Rather than typing the commands manually, it’s best to copy the commands by clicking on the Code:[Select] button and pasting into the terminal.
You missed the final command so would you please enter this command while in the scripts directory and post the full output:

ls -l

This should list the newly named and permissioned file - just to check that everything has gone according to plan, before taking the next step.
I’m sorry it seems like a lot of palava but once it’s done, it will all be much easier next time. Honestly!

Keith