0

I'm working on a quick script in bash where at the beginning, I set IFS=$'\n' . Right after I have a for loop:

for i in *;
do
    j=${i//:/}
done

No matter what I do, a colon is never removed from $i. I tried every method I could think of to remove characters from a string including sed, tr and more. I even tried using a backslash before the colon, or resetting IFS within the for loop.

The strange thing is that I can replace other characters, it's just the colon that's not working for me.

What should I do?

(Here's essentially the whole thing)

#!/bin/bash

IFS=$'\n'
for i in *;
do
    one=${i//:/} ###no colons
    two=${one::-4} ### remove file format
    three=${two,,} ###make lowercase
    four=${three// /-} ### replace spaces with dashes
    five=${four//\'} ### remove any apostropes
    six=${five//.} ### remove any periods
    mkdir /home/"$whoami"/project/"$six"
done

IFS=$' \t\n'
  • `*` does filename expansion, so unless there are files with `:` in their names, there won't be any colons to remove. Not clear what `IFS` has to do with this as you aren't reading any input. – Chris Dodd May 06 '23 at 01:46
  • 1
    It's a bad idea to have colons in filenames, partly because it's not a legal character in filenames on Windows. It's possible that you are dealing with filenames that have been made Windows-friendly by replacing colon with a Unicode character that looks like a colon. Run `printf '%q\n' *` in the directory containing the files with colons in their names. The output should reveal if the colons are not what they seem to be. – pjh May 06 '23 at 02:00
  • I'm creating folders with the same name as files, but making the name lowercase, changing spaces to dashes and since some of the files have colons in the name, getting rid of those – MeepleDeMeep May 06 '23 at 02:20
  • 1
    [Shellcheck](https://www.shellcheck.net/) identifies some problems with the code. The report includes links to more information about the problems and how to fix them. It's a good idea to run [Shellcheck](https://www.shellcheck.net/) on all new and modified shell code. – pjh May 06 '23 at 02:44
  • The modifications to `IFS` are useless if you fix the missing quotes in the `mkdir` command. – pjh May 06 '23 at 02:46
  • Run the code with tracing enabled to see what it is doing. Running with `bash -x PROGRAM_PATH` is one way to do it. See [How can I debug a Bash script?](https://stackoverflow.com/q/951336/4154375). – pjh May 06 '23 at 02:48
  • Since you're not reading any input, the modification to `IFS` is meaningless. What to you expect it to affect? You can just delete those two lines and the behavior will be exactly the same. – Chris Dodd May 06 '23 at 04:29
  • 1
    Are you sure those are colons and not U+2236 or something? What does `ls *:*` say? – glitch May 06 '23 at 05:01

2 Answers2

1
  • ${string/substring/replacement} is Bash string expnasion syntax, which in this case is correct.
  • IFS='\n' sets Internal Field Seperator (i.e., word boundary) to newline, so bash can read escape sequences (newline) within the string. Default is space,tab, and newline.

You're trying to read all file names in the current directory, and remove colon if they have any. The above shell script works perfectly fine in my computer (Ubuntu 22.04, Bash version 5.1.16):

❯ ls
fi:le1.txt  file:2.txt  file:multiple:3.jpg  remove_colon.sh
❯ cat remove_colon.sh
#!/bin/bash

IFS=$'\n'

for i in *;
do
  j=${i//:/}
  echo "$j"
done
❯ ./remove_colon.sh
file1.txt
file2.txt
filemultiple3.jpg
remove_colon.sh
Deepak D
  • 148
  • 11
  • That very much makes sense and should work, but isn't working within the for loop, only outside of it and I can't figure out why – MeepleDeMeep May 06 '23 at 01:53
  • I think `set -o noglob` is present somewhere above this block in your script, which disables `*` wildcard expansion in for loop. If so, undo it with `set +o noglob`. – Deepak D May 06 '23 at 02:08
  • noblob doesn't change anything – MeepleDeMeep May 06 '23 at 02:21
  • Its `noglob`, and make sure you add it (`set +o noglob`) just above the for statement. I think you're missing something straightforward; difficult to debug without seeing other statements. – Deepak D May 06 '23 at 02:29
  • I did add ```set +o noglob``` right above, I just commented it back wrong. I also think it's something stupid and obvious I haven't realized, but usually I realize my mistake by now – MeepleDeMeep May 06 '23 at 02:36
0

I don't understand what IFS has to do with colons in your strings, but $(echo $i | sed 's/://') should be able to replace the colon with a blank space.

pabloabur
  • 24
  • 3
  • I wish it helped, but that doesn't do anything for some reason. The reason I think the problem has to do with IFS is because I can replace colons outside the loop, but not within it – MeepleDeMeep May 06 '23 at 01:32
  • Can you update your question with a minimal working example reproducing the error? – pabloabur May 06 '23 at 02:12