LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Need File Name comparison help on Korn Shell Script (https://www.linuxquestions.org/questions/programming-9/need-file-name-comparison-help-on-korn-shell-script-887707/)

confusiac437 06-22-2011 05:32 AM

Need File Name comparison help on Korn Shell Script
 
I am trying to compare two filenames including the paths. Basically if two paths are similar then my program wants to display message. So I need to check for if two pathnames are same in the sorce and destination. So I was trying for the code to compare tow filename sincluding "\" and if the Parent FIle Path is found in the child file path then I need to displays ome message. I was trying to modify something like this:
#!/bin/ksh
# Sample script

file1="C:\Text\Latest\Article\News.txt"

file2="C:\Text\Latest"

pattern1=$file2

if [[ $file1 = pattern1* ]]
then
echo "Do something"
fi

========================================
Also tried == and $file2 in place of pattern1.

colucix 06-22-2011 05:54 AM

You might try the regular expression match operator:
Code:

#!/bin/ksh
file1="C:\Text\Latest\Article\News.txt"
file2="C:\Text\Latest"

if [[ $file1 =~ $file2 ]]
then
  echo "Do something"
fi

Anyway the backslashes in the file names may confuse the shell which interprets them as escape characters. For this reason it is convenient to change them into a slash or some other character to do the comparison:
Code:

#!/bin/ksh
file1="C:\Text\Latest\Article\News.txt"
file2="C:\Text\Latest"

if [[ ${file1//\\//} =~ ${file2//\\//} ]]
then
  echo "Do something"
fi

Hope this helps.

grail 06-22-2011 06:46 AM

Well I am not sure why you have copied file2 into pattern1, but ultimately you only made 2 small typos to get your script to work as is:
Code:

#!/bin/ksh
# Sample script

file1="C:\Text\Latest\Article\News.txt"

file2="C:\Text\Latest"

pattern1=$file2

if [[ $file1 = "$pattern1"* ]]
then
    echo "Do something"
fi


confusiac437 06-28-2011 12:16 PM

Need More Clarification
 
The approaches suggested do help. But I am trying something like:

##Logic
#Need to copy from one file-path to other file-path
#e.g. from D:\Books\Latest\Novels\Finkler to D:\Books\Latest
#The two string approach would give match even if the destination is only D:\.
#So introduced third string str (which is constant) to check for match with str2 first
#Then compare the fixed path in str3 with str

#! /bin/ksh
str=$1
str2=$2
str3="D:\Books\Latest"
echo $str
echo $str2
if [[ $str2 == [$str3]* ]] then
if [[ $str == [$str2]* ]] then
echo "Go"
else
echo "NoGo1"
fi
else
if [[ $str == [$str3]* ]] then
echo "Go2"
else
echo "NoGo2"
fi
fi

The above code gives me NoGo2 even for matching string.
I am entering arguments as:
D:\Books\Latest D:\Books\Latest\Novels\Finkler

grail 06-29-2011 12:09 AM

So we should have mentioned before, please use [code][/code] tags to make your code more readable and indented.

As for your code:

1. Make sure arguments are passed to script with single quotes around them to preserve the \ and not allow escaping of next character

2. str3 is same as above and needs single quotes

3. Replace [] around comparisons, ie [$str3]*, with "" as I explained in previous post, ie "$str3"*

4. Without any of the changes above your script fails anyway due to missing semi-colon before each of your 'then' statements

Once these changes are made the result I get is: NoGo1, which appears to be correct based on input.

Nominal Animal 06-29-2011 01:47 AM

Quote:

Originally Posted by confusiac437 (Post 4392595)
I am trying to compare two filenames including the paths. Basically if two paths are similar then my program wants to display message.

What do you mean by "are similar"?

If you want to test if string $file1 starts with $file2 or vice versa, use
Code:

if [ "${file1:0:${#file2}}" == "${file2:0:${#file1}}" ]; then
    echo "$file1 starts $file2, or $file2 starts $file1."
fi

If you want the comparison to be case insensitive, use
Code:

typeset -u temp1 temp2
temp1="${file1:0:${#file2}}"
temp2="${file2:0:${#file1}}"
if [ "$temp1" == "$temp2" ]; then
    echo "($file1 prefix) ${file1:0:${#temp1}} and ($file2 prefix) ${file2:0:${#temp}} match."
fi

If you want to find the longest common path prefix, it gets a bit more complicated; especially if you wish to handle symlinks and bind-mounts correctly.

confusiac437 07-01-2011 10:15 AM

Any alternate approaches
 
Code:

if [ "${file1:0:${#file2}}" == "${file2:0:${#file1}}" ]; then
    echo "$file1 starts $file2, or $file2 starts $file1."
fi

If you want the comparison to be case insensitive, use
Code:

typeset -u temp1 temp2
temp1="${file1:0:${#file2}}"
temp2="${file2:0:${#file1}}"
if [ "$temp1" == "$temp2" ]; then
    echo "($file1 prefix) ${file1:0:${#temp1}} and ($file2 prefix) ${file2:0:${#temp}} match."
fi


The above approach does not work for me. Am working in Korn Shell on very old version of Unix.What are the other alternatives in case I basically just want to check if one file path contains other file path in it?

Nominal Animal 07-01-2011 02:14 PM

Well, I have access to ksh on SunOS 5.10, and for it, case seems to work well:
Code:

FILE1="/path/to/some/file"
FILE2="/path/to"

# +u case sensitive, -u is case insensitive
typeset +u TEMP1 TEMP2
TEMP1="$FILE1"
TEMP2="$FILE2"

case "$TEMP1" in
  "$TEMP2")      echo "FILE1 ($FILE1) is the same as FILE2 ($FILE2)" ;;
  "${TEMP2%/}/"*) echo "FILE1 ($FILE1) has prefix FILE2 ($FILE2)" ;;
esac
case "$TEMP2" in
  "${TEMP1%/}/"*) echo "FILE2 ($FILE2) has prefix FILE1 ($FILE1)" ;;
esac

Note that the above uses ${TEMP%/}/ which literally means the value of TEMP, with the trailing slash removed if there is one, with a trailing slash added. Even old Korn shells should support that expression. (I recommend you check, though.)

You'll want to use that, if you do not want /some/path to match /some/path2/file . Otherwise, just use plain $TEMP .

If you are working on a truly ancient Unix, you can always work around the problems by using wc for length, cut for string manipulation, and optionally tr for case conversion:
Code:

FILE1="/some/path"
FILE2="/some/other/path"

LEN1=`echo -n "$FILE1" | wc -c | tr -cd 0-9`
LEN2=`echo -n "$FILE2" | wc -c | tr -cd 0-9`
if [ $LEN1 -gt 0 ] && [ $LEN2 -gt 0 ]; then
    TEMP1="`echo -n "$FILE1" | tr a-z A-Z | cut -b1-$LEN2`"
    TEMP2="`echo -n "$FILE2" | tr a-z A-Z | cut -b1-$LEN1`"
    if [ ":$TEMP1" == ":$TEMP2" ]; then
        echo "FILE1 ($FILE1) is a prefix of FILE2 ($FILE2) or vice versa."
    fi
fi

The above does case insensitive comparison; if you want case sensitive comparison, just replace the | tr a-z A-Z | above with | .

Old shells don't always support $(cmd) subshells, so I use the ancient but equivalent `cmd` instead.

Note that the lengths are intentionally swapped, so that TEMP1 and TEMP2 end up being the same length. I put the colons into the compared patterns just in case your shell does not compare empty strings properly.


All times are GMT -5. The time now is 08:01 PM.