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
#!/bin/bash
#
find "$@" -depth -name '*[[\]]*' -print0 |
while IFS= read -d '' -r item
do
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
done
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
cdto it?cd "$@" && rename 's/...//'?[and]characters from the file names?rename "$@" 's/\(|\[|\]|\)//g' **where"$@"expands to filename(s)/pathname(s) makes no sense. Pathnames must be at the end.renamecan rename the current directory. But its name must be supplied with characters you want to match. This meansrename … ./is futile whilerename … "$(pwd -P)"is often the right way. Does this information advance your research?