1

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,

asked Jul 4, 2018 at 1:18

1 Answer 1

3

Use (perl) rename. The command is as follows:

rename 's/( [0-9]*) .*\.ext/1ドル.ext/' *

N.B. there are two renames 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 expression foo with bar. 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 the extra part of the file name, it will match them.
  • /1ドル.ext Replace this matching part with the capturing group from above 1ドル, i.e. the space and digits, followed by the extension .ext.
answered Jul 4, 2018 at 1:27
6
  • The default for Debian-based distros is the one from perl. On RHEL/CentOS/Fedora, the default is from util-linux. Commented Jul 4, 2018 at 2:32
  • @jordanm Thanks for that info. FWIW Arch also falls in the latter category. Commented 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, etc Commented Jul 4, 2018 at 18:01
  • @kurokirasama Oops, I should have read the question more carefully. I've fixed it. Commented 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? Commented Jul 6, 2018 at 15:51

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.