1

I have a bunch of folders in a directory with files in them. Most of the filenames have region codes (retropie), and the scrubber will not match roms with single letter region codes (u,j,e,etc.). I need to remove all region codes. Region codes are all contained in parentheses "(...)". Is there anyway to remove all parentheses and the text between them?

For example:

Files are titled

~/RetroPie/roms/<system>/

And I want to rename roms like so:

Super Mario Bros (J).nes  
Super Random game (J,U,E).nes  

to

Super Mario Bros.nes  
Super Random game.nes

Hope That fixes the [on hold] tag thing.

closed as unclear what you're asking by Rui F Ribeiro, Jeff Schaller, Michael Homer, jimmij, Alexander Mar 6 at 9:36

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    Examples of filenames and what they would be renamed as would be welcomed. Also, do you have access to the Perl rename utility? – Kusalananda Mar 5 at 21:06
  • 3
    The Perl rename might exist on your system as /usr/bin/file-rename or /usr/bin/prename – glenn jackman Mar 5 at 21:13
  • I might, i'm in school right now. Do I need to be more clear in op? – pcs3rd Mar 6 at 16:31
  • Do you want “to remove all parenthesis and the text between them”, as you say?  If so, does the bit about “the scrubber will not match roms with single letter region codes (u, j, e, etc.)” really matter?  Should Q*bert (spring) be left alone because spring is more than one letter? And what about Abc (def) ghi (J,K)?  (Note: you said that you were going to respond to Kusalananda’s comment, but you didn’t.) – G-Man Mar 6 at 18:17
2

Using the Perl rename utility, if available,

find . -type f -name '* (*)*' -exec rename 's/ \([^)]*\)//g' {} +

This would find all regular files in or below the current directory that have at least one matched set of parentheses in their names. For batches of such files, rename is used to rename the files by removing the parentheses that we know are there, including the leading space before the left parenthesis.

If you don't have rename, then...

Assuming you'd want to remove all parentheses from all names of regular files in the current directory or below, the following find command would do that:

find . -type f -name '* (*)*' -exec bash -O extglob -c '
    for pathname do
        filename=${pathname##*/}
        mv -i "$pathname" "${pathname%/*}/${filename// (!(*\)*))}"
    done' bash {} +

This would locate all regular files whose filename has parentheses in it. For batches of these files, a short bash script would be called.

The bash script would iterate over the current batch of found pathnames and would, for each, first extract the filename portion of the pathname, and then rename the file by removing the parentheses and their content.

There are three parameter substitutions used in the code. They are

  1. ${pathname##*/}: This strips off the directory path from the pathname and leaves only the filename. It is, in this instance, the same as $(basename "$pathaname").

  2. ${pathname%/*}: This removes the filename from the pathname and leaves the directory path. This is, in this instance, the same as $(dirname "$pathname").

  3. ${filename// (!(*\)*))}": This is a bash-specific substitution that removes any space+parentheses from the value of $filename. The sub-pattern !(*\)*) is an extended globbing pattern that matches any string that does not contain a ). We use that in removing individual parentheses so that a filename such as 0 (1) 2 (3) is turned into 0 2 and not just 0.

If there are multiple parentheses, all of these would be removed (as illustrated above).

If you are certain that you don't have directories with parentheses like this, then you may use the shorter command

find . -type f -name '* (*)*' -exec bash -O extglob -c '
    for pathname do
        mv -i "$pathname" "${pathname// (!(*\)*))}"
    done' bash {} +

Testing the first command:

$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Mario Bros (J).nes
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Random game (J,U,E).nes
$ find . -type f -name '* (*)*' -exec prename 's/ \([^)]*\)//g' {} +
$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Mario Bros.nes
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Random game.nes

The other commands give the same results.

  • I'm curious why you were downvoted. No one commented. – malan Mar 6 at 18:13
  • @malan No, people sometimes don't feel like commenting when they downvote, and there's no requirement to do so. However, it makes it difficult to correct any errors or misunderstandings. I don't worry about it too much. – Kusalananda Mar 6 at 18:15
  • I was wondering about it, too. – G-Man Mar 6 at 18:16
  • 1
    @G-Man Thanks for the language edits (etc.) – Kusalananda Mar 6 at 19:02
  • 1
    @malan There are two common implementations of rename. One works the way that I have shown here, and it's often referred to as "the Perl rename" (since it's a Perl script). It is sometimes also called prename. The other one, the one you are using, is less flexible, and I don't know very much about it. – Kusalananda Mar 9 at 14:21
3
find . -iname '*.nes' | xargs -I {} rename -n 's/ *\(.*\)//g' "{}"

Verify that output looks good then run it again without the -n to apply the changes.

  • Once I came to understand rename I came to adore it. Answers like this that use find-centric -exec's with mv are much less capable in my opinion. Of course, this could just be my inexperience with find -exec's. – malan Mar 5 at 21:25
  • 1
    @malan The thing with Perl and this utility is that it's not necessarily available on all types of Unix systems by default, but find and mv are. – Kusalananda Mar 5 at 21:35
  • @Kusalananda the OP said retropie which is debian based, and the other half of the market is fedora based, (there are Arch, bsd, solaris and the stragglers that don't make up 1% of the market), all of which have perl AFAIK... and if you are working on a system without such modern basics then it's time to upgrade your toolset or resign yourself to doing things from 1990s scratch. – user1133275 Mar 6 at 1:54
  • Also note that some systems have this Perl-based tool available as prename rather than rename, and that there's at least one other common implementation of rename that is not implemented in Perl and that would not accept the arguments that you give it. – Kusalananda Mar 6 at 6:08
  • 2
    In addition to that, your given command would, I believe, remove not only the parentheses and the text inside them, but also any text between two sets of parentheses. Use a non-greedy regular expression instead. – Kusalananda Mar 6 at 6:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.