For now, iterate over filenames and remove spaces

I am currently working with formatting file names. Below I have a while loop that loops through filenames and replaces white spaces _

and keeps anything after the hyphen intact. Now the problem is with the results of the command find

to format the names. Running this function in the script produces the following:

find: paths must precede expression: rename
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

while read -r file
   new_file=$(echo "$file" | sed -re 's/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/' -e 's/ /_/g' -e 's/_-/-

       echo "mv '$file' '$new_file'"
  done < <(find ./ -type f rename)


File name:

'./My File - KeEp.txt'


File name after:




source to share

2 answers

What do you intend to do rename

in find ./ -type f rename



as the error message tells you, interprets this as a path (for search) and then tells you that adding paths after the arguments is not allowed.

That being said, and as @Beta points out in his comment, using a loop while

is unnecessary (and fragile) here.

Try this instead:

find ./ -type f -exec bash -c 'echo "mv \"$1\" \"$(echo "$1" | sed -re '\''s/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/'\'' -e '\''s/ /_/g'\'' -e '\''s/_-/-/g'\'')\""' - {} \;


or to actually do this:

find ./ -type f -exec bash -c 'mv "$1" "$(echo "$1" | sed -re '\''s/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/'\'' -e '\''s/ /_/g'\'' -e '\''s/_-/-/g'\'')"' - {} \;


To explain this a little:

  • the bit '\''

    is how you escape the single quote within a single quoted string (you end the string, escape the single quote, and start the string again).
  • -

    in - {}

    is to insert the argument $0

    , which is the first argument bash

    when running -c

    and other arguments. (Without this, the script must be used $0

    instead $1

    to access the filename.)

Oh, and your original script used single quotes around the variables you wanted to expand, which won't work when you pull the double quotes from the echo command.



I think your main mistake is the "rename" argument to the find command, I don't understand why you put it. There are a few things you could improve, such as not trying to rename files that have the same name after it, and instead of "./" you can just write ".". Also note that your script does not "keep anything after the hyphen intact" because it changes spaces even after that even in your example filename.

I would still use a while loop, since bash + sed propagation for each rename can be eliminated this way. I used the -name argument to search only to work with filenames containing hyphens.

Something like that:

while read -r file; do
    x="${file%%-*}" # before first hyphen
    y="${file#*-}" # after first hyphen
    x="${x,,[A-Z]}" # make it lowercase
    x="${x// /_}" # change all spaces to underscores
    if [ "$file" != "$new_file" ]; then
        echo mv "$file" "$new_file"
done < <(find . -type f -name '*-*')




All Articles