Recursively Rename Files to Ascii Standard

Recursively rename files to ASCII Standard

I guess this would be better:

find . -type f -exec bash -c 'for f do d=${f%/*} b=${f##*/} nb=${b//[^A-Za-z0-9._-]/_}; [[ $b = "$nb" ]] || echo mv "$f" "$d/$nb"; done' _ {} +

find will find all files (-type f), pass them as positional arguments to this Bash snippet:

for f do
d=${f%/*} b=${f##*/} nb=${b//[^A-Za-z0-9._-]/_}
[[ $b = "$nb" ]] || echo mv "$f" "$d/$nb"
done

We split the filename into dirname d and basename b. We use parameter expansions to replace all the unwanted characters with underscores and save that expansion into variable nb. We check that the expansions $b and $nb are distinct (so as to avoid an error with mv), and if they are distinct, perform the renaming.

I left echo so that nothing is actually performed, the commands are only echoed. Remove the echo if it looks good.

Note that this can overwrite files, e.g., files a&b and a_b.

Recursively replacing non-standard charecters from folders and files on win10

How's this? Replacing specific characters, then anything not between space and tilde or tab, like the unicode snowman.

echo hi | set-content filä.txt,filé.txt,fil☃.txt # in script or ise
$pairs = ('ä','a'), ('é','e'), ('[^ -~\t]','_')
dir -r | where name -match '[^ -~\t]' | rename-item -newname {
$name = $_.name
foreach ($pair in $pairs) {
$name = $name -replace $pair
}
$name
} -whatif

What if: Performing the operation "Rename File" on target "Item:
C:\users\admin\foo\filä.txt Destination: C:\users\admin\foo\fila.txt".
What if: Performing the operation "Rename File" on target "Item:
C:\users\admin\foo\filé.txt Destination: C:\users\admin\foo\file.txt".
What if: Performing the operation "Rename File" on target "Item:
C:\users\admin\foo\fil☃.txt Destination: C:\users\admin\foo\fil_.txt".

How to recursively rename files and folder with iconv from Bash

I think the following does everything you want in one pass.

# Update: if this doesn't work, use read -d '' instead
find . -print0 | while IFS= read -d '$\000' f ;
do
orig_f="$f"
# Below is pure bash. You can replace with tr if you like
# f="$( echo $f | tr -d ,\' | tr "$'&'@- " "ya__" )"
f="${f// /_}" # Replace spaces with _
f="${f//\'}" # Remove single quote
f="${f//-/_}" # Replace - with _
f="${f//,}" # Remove commas
f="${f//&/y}" # Replace ampersand with y
f="${f//@/a}" # Replace at sign with a
f=$( iconv -f UTF8 -t ASCII//TRANSLIT <<< "$f" )
new_dir="$(dirname $f)"
new_f="$(basename $f)"
mkdir -p "$new_dir"
mv -i "$orig_f" "$new_dir/$new_f"
done

The find command (no real options needed, other than -print0 to handle filenames with spaces) will send null-separated file names to the while loop (and someone will correct my errors there, no doubt). A long list of assignments utilizing parameter expansion removes/replaces various characters; I include what I think is the equivalent pipeline using tr as a comment. Then we run the filename through iconv to deal with character set issues. Finally, we split the name into its path and filename components, since we may have to make a new directory before executing the mv.

How to rename files recursively to hex base 16

There is below a bash script.
Change the values of dest_dir and source_dir

Do not forget to make it executable with chmod +x flattener.sh

#!/bin/env bash

dest_dir="/var/tmp/flat-files"
source_dir="parent-dir"

if [ ! -d "${dest_dir}" ] ; then
mkdir -p "${dest_dir}"
fi

if [ ! -f "${dest_dir}"/index.dat ] ; then
printf "1" > "${dest_dir}"/index.dat || exit 1
fi

find "${source_dir}" -type f -print0 |\
xargs -0 bash -c ' \
for filename ; do \
index=$(cat '"${dest_dir}"'/index.dat) ;\
printf "%d" $((index+1)) > '"${dest_dir}"'/index.dat ;\
if [[ "${filename}" =~ [.] ]] ; then \
extension=."${filename##*.}" ;\
else \
extension="" ;\
fi ;\
mv -vu "${filename}" '"${dest_dir}"'/$(printf "%X" $index)"${extension}" ;\
done' flattener

Mass file rename in Linux

You can use a single find command:

find -type f -regextype posix-extended -regex '.*/[0-9]{1,3}' -exec mv -v {} {}.jpg \;

Change file names with find and iconv

The problem with using $() in this way is that the subshell executes prior to executing the find command, and not as part of -exec. You can do it, but you'll need to invoke bash. Something like:

find dir/ -type f -exec bash -c 'mv "$1" "$(iconv -f UTF8 -t ASCII//TRANSLIT <<< $1)"' -- {} \;

Keep in mind this will also translit any special chars in directory names as well, which may cause the mv to fail. If you only want to translit the filename, then you could:

find dir/ -type f -exec bash -c 'mv "$1" "${1%/*}/$(iconv -f UTF8 -t ASCII//TRANSLIT <<< ${1##*/})"' -- {} \;

which split the directory portion off and only translits the file name.

Renaming files with sed, escaping issues

Just for the records, look:

$ a='I am a Badly [named] (file) - PLEASE.rename_me.JPG'
$ # lowercase that
$ echo "${a,,}"
i am a badly [named] (file) - please.rename_me.jpg
$ # Cool! let's save that somewhere
$ b=${a,,}
$ # substitution 's/[_ ]/-/g:
$ echo "${b//[_ ]/-}"
i-am-a-badly-[named]-(file)---please.rename-me.jpg
$ # or better, yet:
$ echo "${b//[_[:space:]]/-}"
i-am-a-badly-[named]-(file)---please.rename-me.jpg
$ # Cool! let's save that somewhere
$ c=${b//[_[:space:]]/-}
$ # substitution 's/---/--/g' (??)
$ echo "${c//---/--}"
i-am-a-badly-[named]-(file)--please.rename-me.jpg
$ d=${c//---/--}
$ # substitution 's/()[]//g':
$ echo "${d//[()\[\]]/}"
i-am-a-badly-named-file--please.rename-me.jpg
$ e="${d//[()\[\]]/}"
$ # substitution 's/\./-/g':
$ echo "${e//\./-}"
i-am-a-badly-named-file--please-rename-me-jpg
$ f=${e//\./-}
$ # substitution 's/-\([^-]*\)$/\.\1/':
$ echo "${f%-*}.${f##*-}"
i-am-a-badly-named-file--please-rename-me.jpg
$ # Done!

Now, here's a 100% bash implementation of what you're trying to achieve:

#!/bin/bash
for a in "$@"; do
b=${a,,}
b=${b//[_[:space:]]/-}
b=${b//---/--}
b=${b//[()\[\]]/}
b=${b//\./-}
b=${b%-*}.${b##*-}
mv -i -- "$a" "$b"
done

yeah, done!

All this standard and known as shell parameter expansion.

Remark. For a more robust script, you could check whether a has an extension (read: a period in its name), otherwise the last substitution of the algorithm fails a little bit. For this, put the following line just below the for statement:

[[ a != *.* ]] && { echo "Oh no, file \`$a' has no extension..."; continue; }

(and isn't the *.* part of this line so cute?)



Related Topics



Leave a reply



Submit