0

I have this filename containing 3 whitespaces that I extracted from an access database, it looks like this, single quotes included =>>> 'Test de map.csv' I am trying to replace spaces with underscore within a for loop, inside a .sh, unfortunately, it does not seem to be working with:

for file in `ls *.csv`; do
        mv "$file" `echo "$file" | tr -s ' ' | tr ' ' '_'`
#       mv "$file" `echo "$file" |  sed -e "s/ /_/g" -e "s/[\[{\\']//g"`
#       find . -name "* *" -type f | rename "s/ /_/g"
done

Whereas it works perfectly when I type directly this command :

mv 'Test de map.csv' `echo 'Test de map.csv' | tr -s ' ' | tr ' ' '_'`

Someone might help ?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Benouille
  • 13
  • 1
  • 2
    1. Don't parse `ls` output, just use `for file in *.csv`. 2. If you are using bash shell, check out substring replacement, for example `echo ${file// /_}` – James Brown Dec 13 '21 at 14:36
  • 3
    This is most immediately a quoting bug. You quoted `$file`, but you also need to quote your command substitution. (And don't use backticks -- they've been obsolete since the early 90s, when POSIX standardized `$(...)` for command substitution; it nests better and doesn't change how backslashes and other backticks behave within it) – Charles Duffy Dec 13 '21 at 14:36
  • 1
    So `mv "$file" "$(echo "$file" | tr -s ' ' | tr ' ' '-')"`, if you _were_ going to use a pipeline with `tr` instead of proper [parameter expansion](https://wiki.bash-hackers.org/syntax/pe). – Charles Duffy Dec 13 '21 at 14:38
  • 1
    (and as James says, [ParsingLs](https://mywiki.wooledge.org/ParsingLs) is a no-no, as also described in [BashPitfalls #1](http://mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29)). – Charles Duffy Dec 13 '21 at 14:39
  • `shopt -s extglob; newFile=${file// /-}; newFile=${newFile//+(-)/-}; mv -- "$file" "$newFile"` is where I might land if writing this myself. – Charles Duffy Dec 13 '21 at 14:43
  • The other thing is that your loop over the output of `ls *.csv` is going to call `Test` one word, `de` a second word, and `map.csv` a third word, instead of knowing that `Test de map.csv` is all one filename. You avoid that problem when you take `ls` out of the picture. (You could _try_ to avoid it by setting `IFS=$'\n'`, but that doesn't work right for all possible filenames -- the set of possible filenames includes filenames with literal newlines in them). – Charles Duffy Dec 13 '21 at 14:44
  • Thanks for all the good advice :) ! the guys at work still use the backstitch :D I'll take that ! :) – Benouille Dec 13 '21 at 16:42

0 Answers0