2012. március 27., kedd

dangerous bash shell expansions

Recently I saw a forum thread about removing files with filename expansions can be tricky and dangerous when you use the '[A-Z]*' pattern. See the following example.


[qmi@debian: ~/scr/tmp]$ touch ALMA.txt GGG.txt bela.txt lowercase.txt zzz.txt aaa.txt
[qmi@debian: ~/scr/tmp]$ ls
ALMA.txt  GGG.txt  aaa.txt  bela.txt  lowercase.txt  zzz.txt
[qmi@debian: ~/scr/tmp]$ rm -v [A-Z]*.txt
removed `ALMA.txt'
removed `bela.txt'
removed `GGG.txt'
removed `lowercase.txt'
removed `zzz.txt'

Now, the above should have removed all the uppercase filenames, but in fact, it removed all files except for the 'aaa.txt'! Assuming your default settings on Debian Linux (and on other Linuxes as the forum members confirmed) in Bash and the LC_COLLATE variable. After little research into the Bash man page, I found that the LC_COLLATE variable should be set up to 'POSIX' to avoid happening this again. Let's try again.

[qmi@debian: ~/scr/tmp]$ touch ALMA.txt GGG.txt bela.txt lowercase.txt zzz.txt aaa.txt
[qmi@debian: ~/scr/tmp]$ export LC_COLLATE=POSIX
[qmi@debian: ~/scr/tmp]$ rm -v [A-Z]*.txt
removed `ALMA.txt'
removed `GGG.txt'
[qmi@debian: ~/scr/tmp]$

Instead of using the filename expansion metacharacters, we can use the "[[:upper:]]" regex pattern match to the shell to remove the unwanted filenames with uppercase letters. See below.

[qmi@debian: ~/scr/tmp]$ shopt -u nocaseglob
[qmi@debian: ~/scr/tmp]$ touch ALMA.txt GGG.txt bela.txt lowercase.txt zzz.txt aaa.txt
[qmi@debian: ~/scr/tmp]$ ls
ALMA.txt  GGG.txt  aaa.txt  bela.txt  lowercase.txt  zzz.txt
[qmi@debian: ~/scr/tmp]$ rm -v [[:upper:]]*.txt
removed `ALMA.txt'
removed `GGG.txt'
[qmi@debian: ~/scr/tmp]$ ls
aaa.txt  bela.txt  lowercase.txt  zzz.txt
[qmi@debian: ~/scr/tmp]$


Perfect. It removed just what we wanted! All the lowercase filenames remained.

Nincsenek megjegyzések: