While loop through file names and remove white spa

2019-09-17 04:43发布

I am currently working with formatting file names. Below I have a while loop that runs through file names and replaces white spaces with _ and keeps anything after the hyphen untouched. Now the issue is looping through the results of the find command in order to format the names. When running this in a script the out put is the following :

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

rename.sh

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

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

Filename before:

'./My File - KeEp.txt'

File name after:

'./my_file-KeEp.txt'

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-09-17 05:19

What are you intending rename to do in find ./ -type f rename?

find is, as the error message is telling you, interpreting that as a path (to search) and then telling you that adding paths after arguments is not allowed.

That being said, and as @Beta indicates in his comment, using a while loop here is unnecessary (and fragile).

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 this to actually do it:

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 that a bit:

  • the '\'' bit is how you escape a single quote inside a single quoted string (you end the string, escape a single quote and start the string again).
  • The - in - {} is to pad the $0 argument that is the first argument to bash when run with -c and other arguments. (Without that the script would need to use $0 instead of $1 to access the filename.)

Oh, and your original script used single quotes around variables you wanted to have expanded, that wasn't going to work when you pulled the double quotes from the echo command out.

查看更多
贪生不怕死
3楼-- · 2019-09-17 05:21

I think your main bug is the "rename" argument to the find command, I do not understand why you have put it there. There are a few things you could also improve, for example not trying to rename files which would have the same name after it, and also instead of "./" you can simply write ".". Also note that your script does not "keep anything after the hyphen untouched" because it changes the spaces even after that, even in your example filename.

I would still use a while loop, as spawning a bash + sed for each rename can be eliminated this way. I used the -name argument for find to only work on filenames containing a hyphen.

Something like this:

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
    new_file="${x}-${y}"
    if [ "$file" != "$new_file" ]; then
        echo mv "$file" "$new_file"
    fi
done < <(find . -type f -name '*-*')
查看更多
登录 后发表回答