Dash : compatibility problem with a POSIX command?

Asked by Apteryx

I'm trying to write a script which will translate Ms-dos files (CR+LR style) to Unix style files (LF only).
For that purpose, I use the following grep command :
$ grep -l $'\r\n' dosfile.txt
where doxfile.txt is a file save by a windows text editor (notepad), containing some lines.
This command searches inside doxfile.txt for the end of line characters '\r\n' (or hex 0D0A) and prints the name of the file (in that case 'dosfile.txt' if there is a match.

In the terminal (which uses Bash), it works great and the name of the file is print when I run my command on the dosfile.txt.

The problem is with Dash. I made the following script for testing purposes :

#sh is a symbolic link to dash
cd ~/Desktop # the text file is on my desktop
grep -l $'\r\n' dosfile.txt # exact same grep command

What you will notice (if your text file is truly of the ms-dos style) is that it does the inverse of the same grep command in the bash shell.

The command "grep -l $'\r\n' dosfile.txt" in the script returns nothing (normal behavior for an ms-dos text file would have been to print the name of the file, since '\r\n' exists)

Putting #!/bin/bash at the first line of my script fixed it for now.

Why would Dash not interpret rightfully the above grep command, considering the command is POSIX compliant (and so is supposed to be Dash) ?

Thank you!

Question information

English Edit question
Ubuntu dash Edit question
No assignee Edit question
Solved by:
Robert Di Gioia
Last query:
Last reply:
Revision history for this message
Best Robert Di Gioia (digioiar) said :

You need to include the $ inside the single quotes (or drop it altogether, it isn't really necessary as it isn't likely that a \r\n will occur anywhere in a DOS text file except at the end of the line).

In dash, $ expands to the process id, so you're grepping for a certain number followed by \r\n, which grep didn't find.

In bash, $'string' expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.

Hope this helps

Revision history for this message
Apteryx (maxco) said :

Thank you!

I have test with grep -l '$\r\n' or grep -l '\r\n' but it wouldn't work. So I concluded I had to find an equivalent for bash $' ' escape sequence expansion, which I found on that excellent page : https://wiki.ubuntu.com/DashAsBinSh

A posix replacement for $'\r\n ' is to use $(printf '\r\n') instead. I tested it, and it works well!

The script I made is intended to be place in ~/.gnome2/nautilus-scripts. Script will be available in the "Scripts" context menu when you right click on a file. Comments and dialogs are in french. :

# Script qui permet de changer le format d'un fichier texte de MS-DOS à Unix ou vice-versa

if [ "$(grep -L $(printf '\r\n') "$1")" = "$1" ]; then # Teste s'il s'agit d'un fichier de type UNIX
 zenity --question --title "Convertisseur UNIX <-> MS-DOS" --text "Le fichier texte actuel est au format Unix. Souhaitez-vous convertir ce fichier au format MS-DOS?";
 if [ "$?" = "0" ]; then
  sed -i -e 's/$/\r/' "$1" # On insère des CR (\r) à la fin de chaque ligne pour obtenir CR+LF
elif [ "$(grep -l $(printf '\r\n') "$1")" = "$1" ]; then # Teste s'il s'agit d'un fichier de type MS-DOS
 zenity --question --title "Convertisseur MS-DOS <-> UNIX" --text "Le fichier actuel est au format MS-DOS. Souhaitez-vous convertir ce fichier au format Unix?"
 if [ "$?" = '0' ]; then
  sed -i -e 's/\r$//' "$1" # On enlève les retours de chariots '\r' à chaque fin de ligne pour obtenir LF (\n) seulement.
 zenity --error --text "Mauvais type de fichier ou fichier corrompu!"
 exit 1

exit 0

Revision history for this message
Apteryx (maxco) said :

Thanks Robert Di Gioia, that solved my question.