Resposta curta: veja BashFAQ # 050 .
Resposta longa: geralmente, a melhor maneira de fazer isso é colocando comandos em arrays em vez de variáveis simples (eval is não recomendado - ele tende a criar bugs novos e perigosos). Aqui está o caso 1 do estilo array:
dir="/tmp/Mytests/DirWith2 spaces 2"
cmdToRun=(mkdir -p "${dir}") # Note double-quotes to preserve spaces within $dir
"${cmdToRun[@]}" # This is the standard idiom for expanding an array preserving both spaces and word breaks
Caso 2:
rsync_cmd=(rsync -avz --stats)
rsync_destinationBaseDir="/tmp/ToTestRsync"
ListOfDirToSynchronize=( \
"/opt/dir1/subdir1" "/opt/dir1space 1/subdir1" "/opt/dir1space 1/subdir1space 1" )
rsync_host_from="root@SRV1:"
# A loop on the directories in my ListOfDirToSynchronize
for SourceDir in "${ListOfDirToSynchronize[@]}"; do
( # here we start a subshell to run // rsyncsto speed-up the whole process
cmdToRun=("${rsync_cmd[@]}" "${rsync_host_from}${SourceDir}/" "${rsync_destinationBaseDir}${SourceDir}")
funcLog " | INFO | Directories synchronisation | SubprocessID [${subProcessID}] | running command [${cmdToRun[*]}]"
"${cmdToRun[@]}" >> ${LOG_FILE} 2>&1 #<== this does not work when spaces in the directories
) # end of subshell
done # end of the loop
Observe que na entrada de log eu usei ${cmdToRun[*]}
em vez de ${cmdToRun[@]}
, então ele separará as entradas da matriz com espaços em vez de tratá-las como argumentos separados para funcLog. Isso significa que o log é ambíguo (você não pode informar espaços dentro de nomes de arquivos a partir de espaços entre nomes de arquivos); Se isso for um problema, use $(printf " %q" "${cmdToRun[@]}")
, e ele adicionará aspas / escapes / etc para espaços dentro de nomes de arquivos.