How to rename many files url escaped (%XX) to human readable form

Posted by F. Hauri on Stack Overflow See other posts from Stack Overflow or by F. Hauri
Published on 2012-11-24T10:48:50Z Indexed on 2012/11/24 11:05 UTC
Read the original article Hit count: 209

Filed under:
|
|

I have downloaded a lot of files in one directory, but many of them are stored with URL escaped filename, containing sign percents folowed by two hexadecimal chars, like:

ls -ltr $HOME/Downloads/
-rw-r--r-- 2 user user 13171425 24 nov 10:07 Swisscom%20Mobile%20Unlimited%20Kurzanleitung-%282011-05-12%29.pdf
-rw-r--r-- 2 user user  1525794 24 nov 10:08 31010ENY-HUAWEI%20E173u-1%20HSPA%20USB%20Stick%20Quick%20Start-%28V100R001_01%2CEnglish%2CIndia-Reliance%2CC%2Ccolor%29.pdf
...

All theses names match the following form whith exactly 3 parts:

  • Name of the object -( Revision, and/or Date, useless ... ). Extension

In same command, I would like to obtain unde

My goal is to having one command to rename all this files to obtain:

-rw-r--r-- 2 user user 13171425 24 nov 10:07 Swisscom_Mobile_Unlimited_Kurzanleitung.pdf
-rw-r--r-- 2 user user  1525794 24 nov 10:08 31010ENY-HUAWEI_E173u-1_HSPA_USB_Stick_Quick_Start.pdf

I've successfully do the job in full bash with:

urlunescape() {
    local srce="$1" done=false part1 newname ext
    while ! $done ;do
        part1="${srce%%%*}"
        newname="$part1\\x${srce:${#part1}+1:2}${srce:${#part1}+3}"
        [ "$part1" == "$srce"  ] &&
            done=true ||
            srce="$newname"
      done
    newname="$(echo -e $srce)"
    ext=${newname##*.}
    newname="${newname%-(*}"
    echo ${newname// /_}.$ext
}
for file in *;do
    mv -i "$file" "$(urlunescape "$file")"
  done
ls -ltr
-rw-r--r-- 2 user user 13171425 24 nov 10:07 Swisscom_Mobile_Unlimited_Kurzanleitung.pdf
-rw-r--r-- 2 user user  1525794 24 nov 10:08 31010ENY-HUAWEI_E173u-1_HSPA_USB_Stick_Quick_Start.pdf

or using sed, tr, bash ... and sed:

for file in *;do
    echo -e $(
        echo $file |
            sed 's/%\(..\)/\\x\1/g'
      ) |
        sed 's/-(.*\.\([^\.]*\)$/.\1/' |
        tr \ \\n _\\0 |
        xargs -0 mv -i "$file"
  done
ls -ltr
-rw-r--r-- 2 user user 13171425 24 nov 10:07 Swisscom_Mobile_Unlimited_Kurzanleitung.pdf
-rw-r--r-- 2 user user  1525794 24 nov 10:08 31010ENY-HUAWEI_E173u-1_HSPA_USB_Stick_Quick_Start.pdf

But, I'm sure, there must exist simplier and/or shorter way to do this.

© Stack Overflow or respective owner

Related posts about perl

Related posts about bash