branquito
branquito

Reputation: 4054

lowering filenames from bash script, using awk as a helper

I have the following script I wrote, for renaming files in current directory, using awk

#!/bin/bash

# This script collects filenames from current dir, into list
# and then uses awk to process them, lowering their filenames

[ -f ./tmp.filelist ] && rm tmp.filelist

for file in *
do
    echo $file >> tmp.filelist
done

# if file already not all lowercase, make it lowercase
awk '{ if ($0 != tolower($0))
        printf("mv \"%s\" \"%s\"\n", $0, tolower($0)) | "sh" }

        END { close("sh") }
' tmp.filelist && rm tmp.filelist

Is there some better way of escaping those %s-es in printf before sending them to shell? I am not interested in better way of doing this, like only shell or something, I want to use awk here, and just asking about best way to pass filenames with spaces to shell, whatever might be the case, not just this script.

Upvotes: 1

Views: 56

Answers (2)

Tom Fenech
Tom Fenech

Reputation: 74685

Dealing with nested quotes is always a bit of a hassle but another option would be to use something like this. I've chosen to use system instead of piping to sh:

awk '{lower = tolower($0)} $0 != lower {system("mv '"'"'" $0 "'"'"' '"'"'" lower "'"'"'")}' file

In bash and awk, strings are concatenated together by default, so the '"'"'" ends the first part of the awk one-liner, then adds a single quote (which needs to be wrapped in double quotes), then continues with the awk one-liner. In order to then include the value of $0, the double quotes from the system command then need to be closed. Looks kind of awkward and is arguably no improvement on what you already had but it does avoid escaping.

Compare that with the same method using escaping:

awk '{lower = tolower($0)} $0 != lower {system("mv \"" $0 "\" \"" lower "\"")}' file

By the way, the structure of awk scripts is condition { action } so the if statement is redundant. To avoid calling lower twice I added an action which happens unconditionally at the start of the script, which stores the value in the variable lower.

Upvotes: 1

anubhava
anubhava

Reputation: 785761

No need to use awk. In BASH 4+ you can use:

echo "${str,,}"

OR else:

for file in *; do
   mv "$file" "${file,,}"
done

Upvotes: 2

Related Questions