I wrote the next test shell script:
#!/bin/sh
IFS=$'\n'
for d in `find . -name *.cue -print0 | xargs -0 -n1 dirname | sort --unique`
do
unset IFS
echo "$d"
IFS=$'\n'
done
unset IFS
If I execute the find command of the condition in the bash I obtain something like this:
./[FLAC] Destination Goa - The Sixth Chapter (CD)/CD2
./[FLAC] Eat Static - Implant - (CD)
./[FLAC] Elysium - Dance For The Celestial Beings (CD)
./[FLAC] Elysium - Monzoon 1996 (CD)
./[FLAC] Etnica - The Juggeling Alchemists Under The Black Light
(the name of the folders containing cue files)
In the shell script I want to loop using each one of this folders but, of course, if I don't redefine the IFS the occurreances breaks with spaces:
Experience
4
./[FLAC]
VA
-
Trancentral
Five
A
Sonic
Initiation
./[FLAC]
VA
-
Trancentral
In other computer (a MacOS) I solved this problem changing the IFS to breaklines with this command IFS=$'\n'
but in my home computer (an Ubuntu Linux) the loop breaks occurrences with "n":
tra
ce - A Trip To Psychedelic Tra
ce (CD)/CD1
./[FLAC] VA - Ta
tra
ce - A Trip To Psychedelic Tra
ce (CD)/CD2
./[FLAC] VA - Tech
o Tra
ce Ma
Do you know what's happening and why the different behaviour between computers?
Thank you.
You can set IFS to to a newline like this:
IFS="
"
$'\n'
is ksh93/bash/zsh syntax but it is not POSIX syntax. On most current systems #!/bin/sh
points to a POSIX shell (although this is not demanded by POSIX and Solaris 9,10 is an exception).
Whether that shell happens to understand $'\n'
is not something you should rely on. If you want to use $'\n'
change you shebang to #!/bin/bash
or one of the other shells..
On Ubuntu and debian linux and derivatives /bin/sh
points to dash
. With some other distributions it points to /bin/bash --posix
(bash in posix mode)...
Another point to note is that if you unset IFS you are not returning to the previous state, which is IFS that contains a space, a TAB and a newline. By unsetting IFS , field splitting will be done as if IFS contains a space, a TAB and a newline, so all seems well.
Unsetting IFS can give complications, however, if this is mixed with the regular practice
unset IFS # Unset the IFS variable so it does not exist
oldIFS=$IFS # The old state is supposedly saved
IFS=: # IFS is set to some string
IFS=$oldIFS # Now IFS is set to the empty string, which means no field
# splitting is performed at all
You don't need the loop at all. This should do what you want:
find . -name *.cue -print0 | xargs -0 -n1 dirname | sort --unique
If you really want to loop over the results, you should use while
rather than for
:
while IFS= read -r line; do
printf '%s\n' "$line"
done < "$file"
or
my_script | while IFS= read -r line; do
printf '%s\n' "$line"
done
Going back to the question about splitting on a literal n
character, it could be that /bin/sh
on your Ubuntu machine doesn't support the $''
bashism.