Rename multiple .txt files changing some characters in specific positions

Rename multiple .txt files changing some characters in specific positions



I have a collections of hundreds of .txt files in the same folder in Ubuntu 16.04, and they're named with strings and index numbers, like that:


a01_s01_e01_skeleton.txt
a01_s01_e02_skeleton.txt
a01_s01_e03_skeleton.txt
a01_s02_e01_skeleton.txt
...
a20_s10_e02_skeleton.txt
...



I must remove the 0 (zeros) from every .txt file where the number is smaller than 10, so in the end I'll have:


instead of : a01_s01_e01_skeleton.txt

it will be: a1_s1_e1_skeleton.txt #notice that the 0s are gone.



EDIT



The position of the numbers is always the same, like in the examples. The files have a logic of order, so the renaming process must be totally correct.



How could I do that using the command line?





Useful additional info would be if the position of the numbers in the string is always the same or not, and if possible dupes might occur after renaming. If so, what do do then.
– Jacob Vlijm
Aug 30 at 16:05






The position of the numbers in the string is always the same.
– Elisa Maria Alves
Aug 30 at 16:10





Have you tried anything for yourself? Or are you expecting us to write this for you?
– j-money
Aug 30 at 16:41




5 Answers
5



Ok, just for fun, no doubt there are shorter cli solutions, but in python, the script below does the job if the directory is "flat" (as you say) and all files in it are valid files to rename. If not, we need to add an exception, so here we go:


import shutil
import sys
import os

dr = sys.argv[1]

for f in os.listdir(dr):
sections = f.split("_")
newname = "_".join(
[s[0] + str(int(s[1:])) for s in sections[:3]] + [sections[-1]]
)
shutil.move(os.path.join(dr, f), os.path.join(dr, newname))


rename_stuff.py



Run it with the directory as argument:


python3 /path/to/rename_stuff.py </directory/with/files>



As always, first try on a sample directory.



Read the files in the directory:


for f in os.listdir(dr):



Split the name by "_":


sections = f.split("_")



On the first three sections, replace the two (or more) -digit number by its int- ("real") value, so 01 -> 1, 10 -> 10, 020 -> 20, 000300 -> 300 and so on.



Subsequently, glue the sections together again:


newname = "_".join(
[s[0] + str(int(s[1:])) for s in sections[:3]] + [sections[-1]]
)



With the perl rename, you can remove zeroes that occur between a non-digit and a digit.


rename


$ touch a01_s01_e01_skeleton.txt a01_s01_e02_skeleton.txt a01_s01_e03_skeleton.txt a01_s02_e01_skeleton.txt a20_s10_e02_skeleton.txt
$ rename -n 's/(?<=D)0+(?=d)//g' *.txt
rename(a01_s01_e01_skeleton.txt, a1_s1_e1_skeleton.txt)
rename(a01_s01_e02_skeleton.txt, a1_s1_e2_skeleton.txt)
rename(a01_s01_e03_skeleton.txt, a1_s1_e3_skeleton.txt)
rename(a01_s02_e01_skeleton.txt, a1_s2_e1_skeleton.txt)
rename(a20_s10_e02_skeleton.txt, a20_s10_e2_skeleton.txt)



rename may or may not be the perl version. On my system it is called file-rename and it has an alternatives symlink as /usr/bin/rename


rename


file-rename


/usr/bin/rename



Using rename alias rename.ul installed from the package util-linux, I made the following bash shellscript, that I think can do the job for you.


rename


rename.ul


#!/bin/bash

#####################


doer ()

# removes "0" from the string "parameter0"
# for example a0 --> a

rename "s/$10/$1/" *

#####################

# main

#####################

doer a
doer s
doer e



Let us call the shellscript renamer and give it execute permissions.


renamer



If zeros to be removed are preceded by other letters than a,s,e, please add a call of doer with those letters into the script and modify the shellscript, if there are instances, not shown by your sample file names, which need more details in the substitute specification (the function doer).


doer


doer



Create and check 'original' files


$ touch a01_s01_e01_skeleton.txt a01_s01_e02_skeleton.txt a01_s01_e03_skeleton.txt a01_s02_e01_skeleton.txt a20_s10_e02_skeleton.txt
$ ls -1
a01_s01_e01_skeleton.txt
a01_s01_e02_skeleton.txt
a01_s01_e03_skeleton.txt
a01_s02_e01_skeleton.txt
a20_s10_e02_skeleton.txt
renamer



Run the shellscript


$ ./renamer



Check the result


$ ls -1
a1_s1_e1_skeleton.txt
a1_s1_e2_skeleton.txt
a1_s1_e3_skeleton.txt
a1_s2_e1_skeleton.txt
a20_s10_e2_skeleton.txt
renamer
$





why not change your regex to include all your alpha arguments and only run the function once (without any arguments)? Or better yet, just skip defining the function. rename "s/[ase]0/$1/" * all by itself does the trick.
– Dennis Williamson
Aug 30 at 21:39


rename "s/[ase]0/$1/" *





@DennisWilliamson, The command that you suggest does not work for me. I could change my regex to something more complicated or difficult to understand, but if my current script solves the problem of the OP, why make it more complicated? (There is no indication from the OP yet, which answer is preferred for the real case.)
– sudodus
Aug 31 at 4:43






Sorry I missed that you were also using the argument on the right hand side. You could simply change the whole thing to use capture groups.
– Dennis Williamson
Aug 31 at 12:58





Sorry in advance, but I've never worked with shellscript bash files before, and I'm confused about where to save the rename.ul file and how to make it run through the command line.
– Elisa Maria Alves
Aug 31 at 14:42





@ElisaMariaAlves, rename alias rename-ul comes with the package util-linux, which is normally installed by default in Ubuntu. So you need not worry about installing it. I mentioned it because there are other rename programs, that might work differently. So it runs when called (by the command line with it) as described in my answer. -- But I understand that you prefer another answer, which is OK for me. That answer is a good one. -- Good luck :-)
– sudodus
Aug 31 at 15:24



rename


rename-ul


rename



Perl's rename utility is the best option for this, I think.


rename 's/(w)0(d)/$1$2/g' *.txt



This command will replace all occurrences of a letter followed by a zero followed by a digit, retaining the letter and the digit while discarding the zero, for every text file in the current directory.



Using zsh:


autoload zmv
zmv 'a(<->)_s(<->)_e(<->)_skeleton.txt' 'a$1#0_s$2#0_e$3#0_skeleton.txt'





I do not get it
– Pierre.Vriens
Aug 31 at 4:21





Welcome to Ask Ubuntu :-) Please edit your answer and provide a bit more information on how your command works as a ton of people don't get it (bash is the standard) and then your answer is likely to be deleted because of "low quality" even though it's 100% correct. ¯_(ツ)_/¯
– Fabby
Aug 31 at 23:35




Required, but never shown



Required, but never shown






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)