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
    Aug 14 '20 at 8:24
  • @pLumo by using cd I'm in the directory I want to rename, that don't work..
    – JoBe
    Aug 14 '20 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?
    – roaima
    Aug 14 '20 at 8:41
  • I think rename "$@" 's/\(|\[|\]|\)//g' ** where "$@" expands to filename(s)/pathname(s) makes no sense. Pathnames must be at the end. Aug 14 '20 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? Aug 14 '20 at 8:58

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
    Aug 14 '20 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. Aug 14 '20 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
    Aug 14 '20 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
    Aug 14 '20 at 9:46
  • 1
    @roaima Thanks for the extra information, now I understand better!
    – JoBe
    Aug 14 '20 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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