I'm trying to do a script which lists files on a directory and then searchs one by one every file in other directory. For dealing with spaces and special characters like "[" or "]" I'm using $(printf %q "$FILENAME") as input for the find command: find /directory/to/search -type f -name $(printf %q "$FILENAME"). It works like a charm for every filename except in one case: when there's multibyte characters (UTF-8). In that case the output of printf is an external quoted string, i.e.: $'file name with blank spaces and quoted characters in the form of \NNN\NNN', and that string is not being expanded without the $'' quoting, so find searchs for a file with a name including that quote: «$'filename'».
Is there an alternative solution in order to be able to pass to find any kind of filename?
My script is like follows (I know some lines can be deleted, like the "RESNAME="):
#!/bin/bash if [ -d $1 ] && [ -d $2 ]; then IFSS=$IFS IFS=$'\n' FILES=$(find $1 -type f ) for FILE in $FILES; do BASEFILE=$(printf '%q' "$(basename "$FILE")") RES=$(find $2 -type f -name "$BASEFILE" -print ) if [ ${#RES} -gt 1 ]; then RESNAME=$(printf '%q' "$(basename "$RES")") else RESNAME= fi if [ "$RESNAME" != "$BASEFILE" ]; then echo "FILE NOT FOUND: $FILE" fi done else echo "Directories do not exist" fi IFS=$IFSS As an answer said, I've used associative arrays, but with no luck, maybe I'm not using correctly the arrays, but echoing it (array[@]) returns nothing. This is the script I've written:
#!/bin/bash if [ -d "$1" ] && [ -d "$2" ]; then declare -A files find "$2" -type f -print0 | while read -r -d $'\0' FILE; do BN2="$(basename "$FILE")" files["$BN2"]="$BN2" done echo "${files[@]}" find "$1" -type f -print0 | while read -r -d $'\0' FILE; do BN1="$(basename "$FILE")" if [ "${files["$BN1"]}" != "$BN1" ]; then echo "File not found: "$BN1"" fi done fi
IFSS="$IFS", thanIFS="$IFSS"-vswitch inprintfinstead of fork:printf -v BASEFILE "%q" "${file##*/}"export LANG=Cat top of your script (and whipe allprintf "%q"as this is useless while you enclose all variables by double quotes:BASEFILE="$(...)"andif [ -f $2/"${BASEFILE##*/}" ]... and maybe: care about leading newline\n:STRING="${STRING//$'\n'}"find "$2"is necessary.