To rename directories containing left & right squares you can use:

shopt -s globstar 
rename -n 's/\(|\[|\]|\)//g' **

This will rename everything with [ & ] from the directory you're in and recursive..

but I need to execute this as a nemo.action script, and can't get it to work. (Basically a normal bash script)

My current script is:

shopt -s globstar 

rename  "$@" 's/\(|\[|\]|\)//g' **

where $@ is /media/sf_Mediaserver3/Untitled Folder/[ hdjue] [kskk]

where the [ hdjue] [kskk] (just random letters) is the starting folder that I want to rename and the following files/folders...

This doesn't work of course, and now I have to go to the parent directory and run the first lines, but that would process ALL directories in the parent directory, not only the [ hdjue] [kskk] anybody got any idea how to solve this?

it almost seems like the rename function can't handle a start directory?

And if possible, remove all spaces (replace with . (dot)), and make the filename/directory lowercase, to simplify the compatibility with external/internal requests..

  • Sure not, why should it, but can't you simply cd to it? cd "$@" && rename 's/...//' ?
    – pLumo
    Commented Aug 14, 2020 at 8:24
  • @pLumo by using cd I'm in the directory I want to rename, that don't work..
    – JoBe
    Commented Aug 14, 2020 at 8:30
  • The script should accept an argument that's a directory, and then rename not only that directory but also all its files and subdirectories (recursively)? And the rename operation is simply to get rid of [ and ] characters from the file names? Commented Aug 14, 2020 at 8:41
  • I think rename "$@" 's/\(|\[|\]|\)//g' ** where "$@" expands to filename(s)/pathname(s) makes no sense. Pathnames must be at the end. Commented Aug 14, 2020 at 8:47
  • In my Ubuntu (Larry Wall's) rename can rename the current directory. But its name must be supplied with characters you want to match. This means rename … ./ is futile while rename … "$(pwd -P)" is often the right way. Does this information advance your research? Commented Aug 14, 2020 at 8:58

1 Answer 1


The requirement here, as I understand it, is to remove all instances of the [ and ] characters from files and directories at and under the specified paths.

The difficulty is to avoid renaming the directory while it's still being traversed. The globstar ** lists items from the root down rather than depth first, so given an example such as a a/b a/b/c, renaming a will mean that the paths to a/b and a/b/c are no longer valid. The find option can handle this with its -depth, but that requires a different approach

find "$@" -depth -name '*[[\]]*' -print0 |
    while IFS= read -d '' -r item
        path="${item%/*}" file="${item##*/}"    # Separate path and file name parts
        name="${file//[[\]]/}"                  # Generate new file name
        name="${name// /.}"                     # Comment: space becomes dot
        name="${name,,}"                        # Comment: lowercase name

        echo mv -f "$item" "$path/$name"        # Rename

Remove echo (or supplement it) when you are happy the script will do what you expect.

I've used -print0 in conjunction with the -d '' option for read to handle files with really strange filenames (including those with newlines and non-printing characters). You can remove both if you want to see what is going on - or if your implementations don't support them - but the script then becomes less robust

The modifiers when assigning the variables path, file, and name match using globs (not regular expressions). A single modifier (%, #, /) means a shortest or single match; a double modifier (%%, ##, //) means a longest match or multiple matches. It is all documented in the bash man page but here is my explanation with context:

  • ${item%/*} The % indicates that the shortest match to the glob pattern should be removed from the end of the value of $item. So for a/b/c we would remove text matching /* leaving a/b
  • ${item##*/} The ## indicates that the longest match to the glob pattern should be removed from the beginning of the value of $item. So for a/b/c we would remove text matching */ leaving c
  • ${file//[[\]]/} The // indicates that multiple replacements of the glob should be replaced with the text following the next /, i.e. nothing. The glob is a square-bracketed collection of the two characters [ and ], meaning "either [ or ]". So for ab[cd]ef[gh we would end up with abcdefgh
  • wow, that worked, not that I fully understand how it exactly works, it was took me a full day to find why my other script that removes spaces and puts . instead, and that was because the filenames had [ ] in them.. if I understand this correctly, it only runs the renaming code if the directory or filename has a [ or a ] in it?
    – JoBe
    Commented Aug 14, 2020 at 9:18
  • 1
    @JoBe I remember your previous question. The code there might misbehave for filenames with [ and/or ] because you didn't quote the variable properly. This leads me to a hypothesis: you keep "fixing" filenames by removing troublesome characters because you want some flawed scripts/commands to work without errors. I may be wrong. But if I'm right then you should rather concentrate on fixing the scripts/commands. Commented Aug 14, 2020 at 9:34
  • @Kamil actually in trying to write a massive script that processes movies, subtitles, auto renaming and making them compatible with my media system, my next work after solving this is to make it check if the subtitles are duplicates.. oh, I'm also using gio to set the folder icons with country flags depending on what subtitles it has (works good), but as I have written in my profile, I'm dyslexic, and unfortunately beginning to show signs of dementia, so sometimes I can write a code, and the next day don't understand how it works (do a lot of comments nowadays) - a programmers hell..
    – JoBe
    Commented Aug 14, 2020 at 9:43
  • @roaima well, file//[[]]/} for example, I suspect it's regex? don't fully understand ${item##*/} , the ## (if you see my answer to Kamil you might understand why I'm having issues)
    – JoBe
    Commented Aug 14, 2020 at 9:46
  • 1
    @roaima Thanks for the extra information, now I understand better!
    – JoBe
    Commented Aug 14, 2020 at 10:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .