How can I replace numbers in filenames with leading zero in bash? - linux

There are similar questions about how to add numbers with leading zero etc. but in my case my filename has two numbers which is the number of chapter and the number of page. Both lack the leading zero, so they aren't sorted alphabetically. Using rename or any other method I want to convert files like these:
file_1_1.mp3 to file_01_01.mp3
file_1_12.mp3 to file_01_12.mp3
file_12_1.mp3 to file_12_01.mp3
...
I tried this:
rename 's/\d+/sprintf("%02d",$&)/e' *.mp3
but it just add leading zero to the chapter number.

Like this:
rename -n 's/(\d+)_(\d+)\./sprintf("%02d_%02d.", $1, $2)/e' *.mp3
Remove -n switch when the output looks good for you
Output
rename(file_1_12.mp3, file_01_12.mp3)
rename(file_1_1.mp3, file_01_01.mp3)
rename(file_12_1.mp3, file_12_01.mp3)
man rename
There are other tools with the same name which may or may not be able to do this, so be careful.
The rename command that is part of the util-linux package, won't.
If you run the following command (GNU)
$ rename
and you see perlexpr, then this seems to be the right tool.
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo apt install rename
$ sudo update-alternatives --set rename /usr/bin/file-rename
For archlinux:
pacman -S perl-rename
For RedHat-family distros:
yum install prename
The 'prename' package is in the EPEL repository.
For Gentoo:
emerge dev-perl/rename
For *BSD:
pkg install gprename
or p5-File-Rename
For Mac users:
brew install rename
If you don't have this command with another distro, search your package manager to install it or do it manually (no deps...)
This tool was originally written by Larry Wall, the Perl's dad.

This shell script works:
for file in *mp3
do
new=$(echo "$file" | sed 's/_/_0/g; s/_0\([0-9][0-9]\)/_\1/g;');
mv "$file" "$new";
done;
Appends a 0 to each underscore found
Removes that 0 if it resulted in at least digits in a row
Edit: added global flag to the 2nd substitute command, per comment by #PaulHodges

Related

How to change one part of file name in bash?

I am fairly new to Bash and don't know how to do much. I have a series of folder and within those folders I have a few files, for example in the first folder I might have:
file1_0.extension
file1_1.extension
file1_2.extension
...
file1_9.extension
file1_10.extension
file1_11.extension
...
And so on. What I would like to do is write a Bash script that goes through all folders and change the first 10 filenames so that it instead looks like this:
file1_00.extension
file1_01.extension
file1_02.extension
...
file1_09.extension
file1_10.extension
file1_11.extension
...
Would anyone be able to explain how this can be done in Bash? I am fairly new to Bash scripting
You can use "rename" command to do the trick.
First, using "rename -v" to see whether it's installed, if not, you can use this command for Ubuntu
sudo apt install rename
Or for SUSE
zypper install rename
Then simply use
rename -e 's/file1_([0-9]).extension/file1_0$1.extension/' -- *.extension
This can rename the files as you'd like to.

How can I change the order of some string in a filename

I have lots of files like these:
tf_CVBV6Z_CVSA1Z_pws2_pcc1.sac
tf_CVBV5Z_CVSA2Z_pws2_pcc1.sac
tf_CVBV4Z_CVSA3Z_pws2_pcc1.sac
tf_CVBV3Z_CVSA4Z_pws2_pcc1.sac
tf_CVBV2Z_CVSA5Z_pws2_pcc1.sac
tf_CVBV1Z_CVSA6Z_pws2_pcc1.sac
and I want to change the order to end up like this:
tf_CVSA1Z_CVBV6Z_pws2_pcc1.sac
tf_CVSA2Z_CVBV5Z_pws2_pcc1.sac
tf_CVSA3Z_CVBV4Z_pws2_pcc1.sac
tf_CVSA4Z_CVBV3Z_pws2_pcc1.sac
tf_CVSA5Z_CVBV2Z_pws2_pcc1.sac
tf_CVSA6Z_CVBV1Z_pws2_pcc1.sac
I tried the rename option but it does not work.
Any thoughts?
Thanks
With perl's rename :
$ rename -n 's/(CV[^_]+)_(CV[^_]+)/$2_$1/' tf_CVSA1Z_CVBV6Z_pws2_pcc1.sac
tf_CVSA1Z_CVBV6Z_pws2_pcc1.sac -> tf_CVBV6Z_CVSA1Z_pws2_pcc1.sac
Remove -n switch when the output looks good.
There are other tools with the same name which may or may not be able to do this, so be careful.
If you run the following command (GNU)
$ file "$(readlink -f "$(type -p rename)")"
and you have a result that contains Perl script, ASCII text executable and not containing ELF, then this seems to be the right tool =)
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo update-alternatives --set rename /path/to/rename
Replace /path/to/rename to the path of your perl rename executable.
If you don't have this command, search your package manager to install it or do it manually (no deps...)
This tool was originally written by Larry Wall, the Perl's dad.

How to replace double spaces with one space in filenames (also subdirectories) (CloudLinux Server release 6.10)

I want to replace double spaces with one space in the filenames of a lot of photos. These photos are located in directory /foto and it's subfolders. How to do this? For example "photo 1.jpg" needs to become "photo 1.jpg"
The best way is to use commandline, because it's on CloudLinux server. (and it is over 50GB of photos). I searched here on Stackoverflow, also Google to find the command I need. I guess rename is the one to use, or mv.
The only things I found were commands about replacing space and replacing other symbols, but not about double (multiple) spaces.
find -iname \*.* | rename -v "s/\s{2}/ /g"
This is the final command which helped me out. I used perl rename, see answer by Gilles
Use this, using Perl's rename :
rename 's/\s{2}/ /g' files*
Remove -n switch when the output looks good.
There are other tools with the same name which may or may not be able to do this, so be careful.
If you run the following command (GNU)
$ file "$(readlink -f "$(type -p rename)")"
and you have a result that contains Perl script, ASCII text executable and not containing ELF, then this seems to be the right tool =)
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo update-alternatives --set rename /path/to/rename
Replace /path/to/rename to the path of your perl rename executable.
If you don't have this command, search your package manager to install it or do it manually (no deps...)
This tool was originally written by Larry Wall, the Perl's dad.

How to understand this SWI-Prolog makefile - how Linux executable is created?

I am trying to compile grammar parser https://github.com/RichardMoot/Grail into Linux program according to instructions https://github.com/RichardMoot/Grail/blob/master/README and http://www.labri.fr/perso/moot/tutorial/install.html. There is manual how to create Linux executable from SWI-Prolog code http://www.swi-prolog.org/FAQ/UnixExe.html. All that is fine. But I can not find in the Makefile https://github.com/RichardMoot/Grail/blob/master/Makefile any compilation command. SWI-Prolo uses swipl command for compilation but this Makefile swipl calls only once - for displaying the version of the swipl.
I experience some hardship in installation and compilation, that is fine, I can execute/debug Makefile line by line and arrive at the result. But there is problem in my case - I can not see the ultimate goal in my makefile: which lines are responsible for the production of object files (if necessary) and which lines are responsible for the creation of the final Linux executable.
This is windowed program. The source code and documentation contains warnings about incompatibility with the SWI-Prolog 7, but that is fine, I can resolvem them myself, but as I said - I can not see the Makefile lines for creation of exe.
The source code is created by eminent scientist and I certainly don't want to disturb him by so low-level technical question. I would be happy if he continues work on theory and doesn't waste time on low level programming questions. Hope, that there are SWI-Prolog experts.
I am using latest (7.x) SWI-Prolog on Ubuntu 16.x and I have already installed all the mentioned prerequisites.
If you look closely at the provided Makefile, you'll find that the rules all and install are defined as follows (comments added by me):
all:
-cd source ; $(edit) g3 > g3.tmp # Replaces placeholders for your
# ... GRAIL_ROOT install directory.
-cd source ; mv -f g3.tmp g3 # Overwrites `g3` with the filled file.
cd source ; chmod a+x g3 # Makes it executable.
install: # Essentially copies all files to
-mkdir $(datarootdir) # ... your install directory.
-mkdir $(datadir)
cp -f $(images) $(datadir)
-mkdir $(bindir)
cp -f source/insertdot $(bindir)
chmod a+x $(bindir)/insertdot
cp -f $(resources) $(datadir)
cp -f source/*.pl $(bindir)
cp -f source/g3 $(bindir)
If you then do the common make && make install you'll end up with two folders installed in your Grail directory: bin and share. Inside the binary directory you'll have the g3 file that, regardless of being a SWI-Prolog source, has this initial line:
#!/usr/bin/swipl -q -g start -f
% [... prolog code.]
This header should allow your console terminal to determine what interpreter to use for this script (in this case, swipl). In my case, executing Grail with ./g3 returned a SWI-Prolog message indicating that wrong options/command arguments were used.
According to the man, Unix systems have to use option -s at the end of the header (but this didn't work either in my case):
From the manual:
-s file
Load file as a script. This option may be used from the shell to
make Prolog load a file before entering the toplevel.
It is also used to turn a file into an executable Prolog script
on Unix systems using the following first line
#!/usr/bin/swipl option ... -s
If you want to run this program, simply call the same command from your terminal:
swipl -q -g start -s g3

How do I read the source code of shell commands?

I would like to read the actual source code which the linux commands are written with. I've gained some experience using them and now I think it's time to interact with my machine at a deeper level.
I've found some commands here http://directory.fsf.org/wiki/GNU. Unfortunately I wasn't able to find basic commands such as 'ls' which seems to me easy enough to begin.
How exactly do I read the source code of the simple shell commands like 'ls'?
I'm running on Ubuntu 12.04
All these basic commands are part of the coreutils package.
You can find all information you need here:
http://www.gnu.org/software/coreutils/
If you want to download the latest source, you should use git:
git clone git://git.sv.gnu.org/coreutils
To install git on your Ubuntu machine, you should use apt-get (git is not included in the standard Ubuntu installation):
sudo apt-get install git
Truth to be told, here you can find specific source for the ls command:
http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c
Only 4984 code lines for a command 'easy enough' as ls... are you still interested in reading it?? Good luck! :D
Direct links to source for some popular programs in coreutils:
cat (767 lines)
chmod (570 lines)
cp (2912 lines)
cut (831 lines)
date (570 lines)
df (1718 lines)
du (1112 lines)
echo (272 lines)
head (1070 lines)
hostname (116 lines)
kill (312 lines)
ln (651 lines)
ls (4954 lines)
md5sum (878 lines)
mkdir (306 lines)
mv (512 lines)
nice (220 lines)
pwd (394 lines)
rm (356 lines)
rmdir (252 lines)
shred (1325 lines)
tail (2301 lines)
tee (220 lines)
touch (437 lines)
wc (801 lines)
whoami (91 lines)
Full list here.
ls is part of coreutils. You can get it with git :
git clone git://git.sv.gnu.org/coreutils
You'll find coreutils listed with other packages (scroll to bottom) on this page.
Actually more sane sources are provided by http://suckless.org look at their sbase repository:
git clone git://git.suckless.org/sbase
They are clearer, smarter, simpler and suckless, eg ls.c has just 369 LOC
After that it will be easier to understand more complicated GNU code.
CoreUtils referred to in other posts does NOT show the real implementation of most of the functionality which I think you seek. In most cases it provides front-ends for the actual functions that retrieve the data, which can be found here:
It is build upon Gnulib with the actual source code in the lib-subdirectory
You can have it on github using the command
git clone https://github.com/coreutils/coreutils.git
You can find all the source codes in the src folder.
You need to have git installed.
Things have changed since 2012, ls source code has now 5309 lines
BSD distributions are actually a nice way of reading the source code, by using their repositories, since it is all packed into one place, and you can view how historically the source code has evolved, or changed. So why not use BSD repos , such as NetBSD or OpenBSD for this task.
cd ~ && apt-get source coreutils && ls -d coreutils*
You should be able to use a command like this on ubuntu to gather the source for a package, you can omit sudo assuming your downloading to a location you own.

Resources