I have some files in the form:
filename1 1 extra1.ext filename1 2.ext filename1 3 extra2.ext ... filename2 1.ext filename2 100 extra3.ext ... filename20 1.ext filename20 15 extra100.ext (etc.)
...where filename1
, filename2
, etc., can contain spaces and symbols like numbers, letters, [
,]
,(
,)
and '
, but not numbers enclosed in spaces. And extra1
, extra2
, etc, can contain anything. The number in the file name enclosed by spaces does not repeat per same filename1
, filename2
, etc.
What i want is to remove the extra things of the files that contain it. That is, to get from filename20 15 extra100.ext
to filename20 15.ext
Moreover, i need to loop this in the content of a directory, so i also need to differentiate between files that have extra things (and then apply the rename method) from files that doesn't.
Is it possible? I just moved from windows to linux, and i have a batch script for this, but i have no idea in how to begin this in bash.
Regards,
1 Answer 1
Use (perl) rename. The command is as follows:
rename 's/( [0-9]*) .*\.ext/1ドル.ext/' *
N.B. there are two rename
s commonly shipped with Linux distributions. The default is usually the simpler version. The perl-based rename is much more powerful, because it gives you access to regular expressions. Make sure you are using the latter. (You don't mention your distro, but in Arch, it's provided by the package perl-rename
.)
Test it first
Create the files (I added an extra file at the end).
$ touch 'filename1 1 extra1.ext' 'filename1 2.ext' 'filename1 3 extra2.ext' 'filename2 1.ext' 'filename2 100 extra3.ext' 'filename20 1.ext' 'filename20 15 extra100.ext' 'filename3 1 3 4 .ext'
Test the command
$ rename 's/( [0-9]*) .*\.ext/1ドル.ext/' * -n
filename1 1 extra1.ext -> filename1 1.ext
filename1 3 extra2.ext -> filename1 3.ext
filename20 15 extra100.ext -> filename20 15.ext
filename2 100 extra3.ext -> filename2 100.ext
filename3 1 3 4 .ext -> filename3 1.ext
If you are happy with the results, then remove the "dry-run"/test flag -n
and run it for real.
Explanation
rename 's/foo/bar/' *
: perl rename will replace an occurrence of the regular expressionfoo
withbar
. This acts on all files*
in the current directory. You could also explicitly replace this with*.ext
to limit which files it acts on./( [0-9]*) .*\.ext
: Match a space followed by a run of digits[0-9]*
followed by another space. Enclose the first space and digits in a capturing group( [0-9]*)
, to reuse later. Then match everything.*
up to and including the extension\.ext
. Because this regex is "greedy", it will try to match as many characters as possible. i.e. if there are digits surrounded by spaces in theextra
part of the file name, it will match them./1ドル.ext
Replace this matching part with the capturing group from above1ドル
, i.e. the space and digits, followed by the extension.ext
.
-
The default for Debian-based distros is the one from perl. On RHEL/CentOS/Fedora, the default is from util-linux.jordanm– jordanm2018年07月04日 02:32:10 +00:00Commented Jul 4, 2018 at 2:32
-
@jordanm Thanks for that info. FWIW Arch also falls in the latter category.Sparhawk– Sparhawk2018年07月04日 06:14:41 +00:00Commented Jul 4, 2018 at 6:14
-
Hello, thankz for your response. You almost got it , but the renaming should keep the first number (from left to right) enclosed by spaces, that is, the output of your example should be
filename1 1.ext
,filename1 3.ext
,filename20 15.ext
, etckurokirasama– kurokirasama2018年07月04日 18:01:19 +00:00Commented Jul 4, 2018 at 18:01 -
@kurokirasama Oops, I should have read the question more carefully. I've fixed it.Sparhawk– Sparhawk2018年07月04日 23:52:09 +00:00Commented Jul 4, 2018 at 23:52
-
@Sparhawk Hi, your solution works fine, but if i also get this output:
1円 better written as 1ドル at (eval 5) line 1
. Where i put the command on a bash file at line 5. Is it ok?kurokirasama– kurokirasama2018年07月06日 15:51:47 +00:00Commented Jul 6, 2018 at 15:51