i am encountered with a use case where there are big list of folders and files which names contain spaces and i need to change the names into camelcase.
any ideas ?
do
newname=`echo $oldname | sed -e 's/ /_/g'`
if [ "$newname" = "$oldname" ]
then
continue
fi
if [ -e "$newname" ]
then
echo Skipping "$oldname", because "$newname" exists
else
mv "$oldname" "$newname"
fi
done
i have found this but it changes the spaces into underscore.
thanks in advance.
CodePudding user response:
Try this Shellcheck-clean Bash code:
#! /bin/bash -p
lowers=abcdefghijklmnopqrstuvwxyz
uppers=ABCDEFGHIJKLMNOPQRSTUVWXYZ
for oldname in *; do
[[ $oldname == *[[:space:]]* ]] || continue
read -r -a parts <<<"$oldname"
newname=''
for p in "${parts[@]}"; do
char1=${p:0:1}
if [[ $lowers == *"$char1"* ]]; then
tmp=${lowers%"$char1"*}
uchar1=${uppers:${#tmp}:1}
newname =${uchar1}${p:1}
else
newname =$p
fi
done
if [[ -e $newname ]]; then
printf "Skipping '%s', because '%s' exists\\n" "$oldname" "$newname" >&2
else
echo mv -v -- "$oldname" "$newname"
fi
done
- The code is intended to work with (the now ancient) Bash 3 because my understanding is that that is still the current version of the standard Bash on macOS. The code for uppercasing the first letter of filename parts is much more complicated than it would be with later versions of Bash (which have built-in mechanisms for case conversion). See How to convert a string to lower case in Bash? for information about changing case in various ways in various versions of Bash.
- The code just prints the
mv
command that would be run. Remove theecho
to make it actually do themv
. - See the accepted, and excellent, answer to Why is printf better than echo? for an explanation of why I replaced
echo
withprintf
for the "Skipping" message.
CodePudding user response:
You can use the regular expression aptitude to deal with upper and lower case translations, regarding your current local collation (LC_ALL
, check with the locale
command).
If your filename's "words" are separated with a space, you can use a simple shell script like this :
#!/bin/sh
while read FILENAME ; do
NEWNAME="`echo \"${FILENAME}\" | sed 's/ *\([^ ]\)/\u\1/g'`"
if [ ! "${NEWNAME}" ] ; then
NEWNAME="${FILENAME}";
fi
if [ "${FILENAME}" = "${NEWNAME}" ]; then
printf "No change : ${FILENAME}\\n" >&2;
continue;
else
if [ -e "${NEWNAME}" ] ; then
printf "Already changed : ${FILENAME} => ${NEWNAME}\\n" >&2;
continue;
else
echo "mv \"${FILENAME}\" \"${NEWNAME}\"";
fi
fi
done
Remove the echo
on echo "mv \"${FILENAME}\" \"${NEWNAME}\"";
to do the mv.
Note that it should work fine with accented letters or any unicode letter having lower and upper code.
The script takes the file list to operate from stdin
, so to use it "as is", you can use something like the following examples :
find . -type 'd,f' | theScript.sh
For a whole tree.
ls -1 | theScript.sh
For files in the current folder.