1

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:

#!/bin/bash

for fname in *; do
    name="${fname%\.*}"
    extension="${fname#$name}"
    newname="${name//[/}"
    newfname="$newname""$extension"
    if [ "$fname" != "$newfname" ]; then
        #echo mv "$fname" "$newfname"
        mv "$fname" "$newfname"
    fi
done

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.

4 Answers 4

3

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

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

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;
1
  • nice! it works , remove all brackets in filename.
    – juicebyah
    Jun 10, 2015 at 9:15
0

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.

2
  • 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, 2016 at 14:16
  • Are you using BASH or ZSH? Are you sure you've copied the code correctly?
    – jficz
    Apr 3, 2016 at 16:22
0

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

name="${fname%\.*}"
extension="${fname#$name}"

results in:

name=[test]
extension=[test]

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

What you should have used:

name=${fname%.*}
extension=${fname#"$name"}

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:

${fname//[][]/}

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.

You must log in to answer this question.

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