Click to See Complete Forum and Search --> : Driving me crazy, case sensitive
pwharff
02-02-2006, 04:32 PM
I have a file I am accessing that constantly changes from all lowercase to all UPPERCASE (this is caused by a wierd bug in some proprietary database we use). My script use to copy this file with no problems until we upgraded our database. So I thought the solution would be easy with an "if" statement:
if
[ -e partmast.dbf ]
then
dbFile="partmast.dbf"
else
dbFile="PARTMAST.DBF"
fi
The strange thing is that "-e" which means "file exists" ignores case. So no matter if the file is really lowercase or UPPERCASE, the result is always dbFile="partmast.dbf"
I thought UNIX/Linux always adhered to proper case. Anyway, if anyone can help me, that would be great. Thank you in advance!
bwkaz
02-02-2006, 07:55 PM
The strange thing is that "-e" which means "file exists" ignores case. No it doesn't, at least not on my system:
$ touch file
$ [ -e FILE ] ; echo $?
1
$ [ -e file ] ; echo $?
0 Maybe someone patched your shell? (Or maybe you aren't using bash?)
Try "/bin/test -e partmast.dbf ; echo $?" while the filename is in uppercase, to see what you get. If you get "1", then the /bin/test tests are case-sensitive. If you get "0", then you have the same problem with /bin/test, and you need to smack the person that made your distro. ;)
pwharff
02-02-2006, 08:11 PM
No it doesn't, at least not on my system:
$ touch file
$ [ -e FILE ] ; echo $?
1
$ [ -e file ] ; echo $?
0 Maybe someone patched your shell? (Or maybe you aren't using bash?)
Try "/bin/test -e partmast.dbf ; echo $?" while the filename is in uppercase, to see what you get. If you get "1", then the /bin/test tests are case-sensitive. If you get "0", then you have the same problem with /bin/test, and you need to smack the person that made your distro. ;)
Hmmmm... I ran that and got a "0". :(
I guess I'll be smacking Apple, since it is OS X. Dang Apple!
leonpmu
02-02-2006, 11:29 PM
Please give a little more detail, is this database being accessed by Windows boxes using samba? If that is the case, then you need to make changes to samba to for the case...
voidinit
02-03-2006, 04:44 AM
Hmmmm... I ran that and got a "0". :(
I guess I'll be smacking Apple, since it is OS X. Dang Apple!
Well if Apple has broken /bin/test, can't imagine why they would do such a thing. Anyway here's a workaround off the top of my head. It works in bash-2.05b or newer at least.
#God this looks stupid. There's got to be a better way.
#You need a path of some sort (./ or /path/to/dir)
# infront of the blocks or a * after them
#so bash knows you are trying to expand a filename.
dbTmp=(./[Pp][Aa][Rr][Tt][Mm][Aa][Ss][Tt].[Dd][Bb][Ff])
if [ ${#dbTmp[@]} -ne 1 ]
then
echo "No files or more than one file matching specification was found."
exit 1
else
dbFile=${dbTmp[0]}
echo "Found file matching specification: $dbFile."
fi
It looks hideous, but it doesn't launch any extra external processes and it will find partmaster.dbf, PARTMASTER.DBF, PaRtMaStEr.DbF or any combination thereof.
You can also do this if the above seems like someone spent a little too much time on the crackpipe.
if ls partmast.dbf 2>&1 > /dev/null
then
dbFile="partmast.dbf"
fi
if [ X$dbFile == "X" ]
then
if ls PARTMAST.DBF 2>&1 > /dev/null
then
dbFile="PARTMAST.DBF"
fi
fi
if [ X$dbFile == "X" ]
then
echo "No files found. Puke and die."
exit 1
fi
As long as ls isn't case-insesitive as well. I like to use [ X$var == "X" ] to check and see if a var is not set rather than [ -z $var ] because I've some -z tests behave differently between versions of bash.
pwharff
02-03-2006, 05:29 PM
Well if Apple has broken /bin/test, can't imagine why they would do such a thing. Anyway here's a workaround off the top of my head. It works in bash-2.05b or newer at least.
#God this looks stupid. There's got to be a better way.
#You need a path of some sort (./ or /path/to/dir)
# infront of the blocks or a * after them
#so bash knows you are trying to expand a filename.
dbTmp=(./[Pp][Aa][Rr][Tt][Mm][Aa][Ss][Tt].[Dd][Bb][Ff])
if [ ${#dbTmp[@]} -ne 1 ]
then
echo "No files or more than one file matching specification was found."
exit 1
else
dbFile=${dbTmp[0]}
echo "Found file matching specification: $dbFile."
fi
It looks hideous, but it doesn't launch any extra external processes and it will find partmaster.dbf, PARTMASTER.DBF, PaRtMaStEr.DbF or any combination thereof.
You can also do this if the above seems like someone spent a little too much time on the crackpipe.
if ls partmast.dbf 2>&1 > /dev/null
then
dbFile="partmast.dbf"
fi
if [ X$dbFile == "X" ]
then
if ls PARTMAST.DBF 2>&1 > /dev/null
then
dbFile="PARTMAST.DBF"
fi
fi
if [ X$dbFile == "X" ]
then
echo "No files found. Puke and die."
exit 1
fi
As long as ls isn't case-insesitive as well. I like to use [ X$var == "X" ] to check and see if a var is not set rather than [ -z $var ] because I've some -z tests behave differently between versions of bash.
Thanks for help, it's greatly appreciated. Just to test your script (the second one), I ran this and got strange output:
#!/bin/bash
if ls partmast.dbf 2>&1 > /dev/null
then
echo "partmast.dbf"
# dbFile="partmast.dbf"
fi
if [ X$dbFile == "X" ]
then
if ls PARTMAST.DBF 2>&1 > /dev/null
then
echo "PARTMAST.DBF"
# dbFile="PARTMAST.DBF"
fi
fi
if [ X$dbFile == "X" ]
then
echo "No files found. Puke and die."
exit 1
fi
And the output is:
partmast.dbf
PARTMAST.DBF
No files found. Puke and die.
Any ideas why? I commented-out the variables and added the echo's just for testing and this is what I got.
bwkaz
02-03-2006, 07:27 PM
Any ideas why? Because your version of ls is also case-insensitive. :(
For that matter, bash may also be case-insensitive. It looks like bash's "test" builtin is (from the testing above); its pathname expansion (the code that expands "[Pp][Aa][Rr][Tt]...") may also be.
pwharff
02-06-2006, 12:16 PM
Because your version of ls is also case-insensitive. :(
For that matter, bash may also be case-insensitive. It looks like bash's "test" builtin is (from the testing above); its pathname expansion (the code that expands "[Pp][Aa][Rr][Tt]...") may also be.
That's so strange. When I navigate to files, edit files or cat files, I always have to make sure I use proper case and always have from OS X 10.0-10.4. Very bizarre. Anyway, thanks for the help.
pwharff
02-06-2006, 07:29 PM
I discovered the root of my "Case" problem. The file that I am trying to distinguish whether it is uppercase or lowercase is within an SMB share and therefore has a different filesystem within that share. Obviously this doesn't effect the entire filesystem. Anyway, just thought you should know. BTW, leonpmu was right, it is a database being accessed via Samba.
bwkaz
02-06-2006, 08:02 PM
Wait, the OSX box is accessing it via Samba? Yes, that would make it fairly obvious (at least to me) that a case issue is going to happen. I thought the file was local, and you were using Samba to share it to windows boxen.
Doubt there's much you can do then...
voidinit
02-07-2006, 02:22 AM
Thanks for help, it's greatly appreciated. Just to test your script (the second one), I ran this and got strange output:
#!/bin/bash
if ls partmast.dbf 2>&1 > /dev/null
then
echo "partmast.dbf"
# dbFile="partmast.dbf"
fi
if [ X$dbFile == "X" ]
then
if ls PARTMAST.DBF 2>&1 > /dev/null
then
echo "PARTMAST.DBF"
# dbFile="PARTMAST.DBF"
fi
fi
if [ X$dbFile == "X" ]
then
echo "No files found. Puke and die."
exit 1
fi
And the output is:
partmast.dbf
PARTMAST.DBF
No files found. Puke and die.
Any ideas why? I commented-out the variables and added the echo's just for testing and this is what I got.
That output appeared because ls isn't piped to /dev/null correctly. It should be ls partmast.dbf > /dev/null 2>&1. I got it backwards. But since it found both the upper and lower case files, then I guess it's a whole nother problem all together.
bigmac99
02-13-2006, 05:36 PM
why don't you just change the case of the file name before you start? then you could have your script always look for the lower case file name?
eval 'exec perl $0 ${1+"$@"}'
if 0;
# don't modify below here
#-------------------------
$VERSION='2.0';
# chcase 2.0
# Changes case of filenames
# http://www.blemished.net/chcase.html
# supermike@blemished.net
#
use Getopt::Std;
use Cwd;
use File::Basename;
sub HELP_MESSAGE {
print<<EOT;
chcase $VERSION
USAGE:
chcase [-terdlouCcqn] [-x '<perl exp>'] FILE...
-t : Test mode (don't actually rename any files)
-e : Print examples
-r : Rename recursively
-d : Also rename directories
-l : Rename & follow symbolic links (default is not to)
-o : Overwrite if file exists
-u : Change to uppercase (default is lower)
-C : Capitalize each word
-c : Capitalize first character only
-q : Quiet mode (no output)
-n : No escape characters (for bold/inverse output)
-x '<perl exp>' : Perl expression to operate on filename
like s/// or tr/// (you need the quotes)
case of filename not changed when this option used
EOT
exit;
}
sub EXAMPLES() {
print<<EOT;
chcase $VERSION
EXAMPLES:
\$ chcase My.DOC *.JPG /tmp/FileName.txt
=> files are changed to lowercase
\$ chcase -rdt .
=> show what would happen if we renamed all files and sub dirs
recursively in pwd to lowercase; remove t to do it for real
\$ chcase -rdoc /some/dir ./images/ *png
=> files and dirs recursively capitalized,
overwrite any existing already capitalized file
\$ chcase -x 's/projectx/PlanB/; s/ /_/g' *.doc
=> renames *.doc files substituting "projectx" with "PlanB",
and replacing all spaces with underscores
\$ find ./music/ -name "*mp3" | xargs chcase -x 'tr/a-zA-Z0-9.-_/_/cs'
=> find mp3 files under music/ dir, transliterate (and squash)
non-alphanumeric characters except for . or - to _
EOT
exit;
}
sub msg {
return if $opt_q; my($ol,$new,$err)=@_;
$out=' 'x($lvl-1).$s.$ol; $out.=" => $new" if $new;
$out.=" : $i$err" if $err; print "$out$n\n";
}
sub chcase {
$_=$old=shift;
$dn=dirname($_).'/'; $dn="" if ($dn eq './');
$_=basename($_);
if ($opt_x) { eval $opt_x; } else { $_=$opt_u ? uc : lc; }
$_=$dn.$_;
return($old) if (($old eq $_) or -d or (-f and !$opt_o));
if ($opt_t or rename($old, $_)) { msg($old,$_); return($opt_t ? $old : $_); }
else { msg($old,$_,$!); return($old); }
}
sub proc {
shift;
if (-l and !$opt_l) { return; }
if (-f) { chcase($_); }
elsif (-d) {
s/\/+$//;
if ($opt_d) { $_=chcase($_); }
if ($opt_r) {
my $cwd=cwd();
if (chdir($_)) { msg("$b$_/"); } else { msg("$b$_/",0,$!); return; }
$lvl++; $s='|__';
opendir(D,'.');
foreach (readdir(D)) { proc($_) unless (($_ eq '.') or ($_ eq '..')); }
closedir(D);
chdir($cwd);
$s='' if (--$lvl == 0);
}
}
}
sub init() {
$Getopt::Std::STANDARD_HELP_VERSION=true;
getopts( 'erdouqtnlCcx:' ) or HELP_MESSAGE();
EXAMPLES() if $opt_e;
unless ($opt_n) {$b="\033[01m"; $i="\033[03m"; $n="\033[0m"; }
$opt_x='s/([^_-\s]+)/\u\L$1/g' if $opt_C;
$opt_x='$_=ucfirst(lc)' if $opt_c;
}
init();
while ($_=shift @ARGV) { proc($_); }
-Charles
I have a file I am accessing that constantly changes from all lowercase to all UPPERCASE (this is caused by a wierd bug in some proprietary database we use). My script use to copy this file with no problems until we upgraded our database. So I thought the solution would be easy with an "if" statement:
if
[ -e partmast.dbf ]
then
dbFile="partmast.dbf"
else
dbFile="PARTMAST.DBF"
fi
The strange thing is that "-e" which means "file exists" ignores case. So no matter if the file is really lowercase or UPPERCASE, the result is always dbFile="partmast.dbf"
I thought UNIX/Linux always adhered to proper case. Anyway, if anyone can help me, that would be great. Thank you in advance!