I've been trying to remove all brackets in my filename(s). Can anyone help me create a bash script to do that?

This bash script below work flawlessly for non-bracket filename(s), but if there are any brackets, it will double the filename:


for fname in *; do
    if [ "$fname" != "$newfname" ]; then
        #echo mv "$fname" "$newfname"
        mv "$fname" "$newfname"

Sample output:

$ touch [test]
$ ls
[test] rep.sh
$ bash rep.sh
$ ls
rep.sh  test][test]

So it did remove the left bracket but it repeated the filename.


i found this one liner and this work :

for x in *[*; do mv -- "$x" "${x//[/}"; done

this should do the job , just replace left or right bracket each time yu execute this commandl

  • you can lose the trailing /; so "${x//[}" instead of "${x//[/}" – iruvar Jun 10 '15 at 1:10
  • 2
    Make that "${x//[][]}" to replace both brackets. (Yes, it does look weird.) – Gilles 'SO- stop being evil' Jun 10 '15 at 14:57

Solution posted by @juicebyah will only remove the initial bracket. If OP wants to remove both brackets, it is better to use sed in this way:

find . -type f -iname "*[*" | \
while IFS= read -r line; \
do mv "$line" "$(printf %s "$line" | sed -re 's/(\[|\])//g')"; done;
  • nice! it works , remove all brackets in filename. – juicebyah Jun 10 '15 at 9:15

It's even simpler with rename embedded in a two-liner:

while rename ] '' *; do true; done
while rename [ '' *; do true; done

rename replaces the first occurrence of $1 with $2 in filename(s) in $3+ and this block removes any and all brackets in all file-and-directorynames in CWD.

  • All I get when trying this is "syntax error at (user-supplied code) line 3, at EOF \ Missing right curly or square bracket at (user-supplied code) line 4, at end of line" – LawrenceC Apr 2 '16 at 14:16
  • Are you using BASH or ZSH? Are you sure you've copied the code correctly? – mikky Apr 3 '16 at 16:22

The reason the filename gets doubled is that if $fname is [test], then


results in:


(Explanation below.) Later, when $extension is concatenated to $newname, you'll get test][test].

What you should have used:


The quotes around the parameter expansion are unnecessary (in this case) because word-splitting doesn't happen after parameter expansion in variable assignments. Also, there is nothing special about ., so there was no need to backslash-escape it.

But the quotes around $name in the second line are essential; if the expansion of $name is not quoted, it will be treated as a glob pattern, and it's value [test] will be interpreted as "a single e, s or t". That doesn't prefix-match $fname, so without those quotes, extension is just set to the value of $fname.

Independent of the above, you can remove all brackets from a name with:


The pattern is a character class; within a character class, ] is considered an ordinary character if it is the first character in the class, and [ is always considered an ordinary character. So the character class consists of ] and [ in that order.

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.