Byrn
Byrn

Reputation: 11

shell script that determines file type

Having trouble with this problem, i could use some help ....

create a shell script, fileType.sh, that takes a single command line parameter, a file path (might be relative or absolute). The script should examine that file and print a single line consisting of the phrase

Windows ASCII

if the files is an ASCII text file with CR/LF line terminators, or

Something else

if the file is binary or ASCII with “Unix” LF line terminators.

For example:

./fileType.sh ~cs252/Assignments/ftpAsst/d3.dat

Windows ASCII

./fileType.sh /bin/cat

Something else

./fileType.sh fileType.sh

Something else

./fileType.sh /usr/share/dict/words

Something else

Your script should not produce any other output when given a legal path to an existing file. (It may produce anything you like if given an incorrect path to a non-existent file.)

New to Unix, I have some C++ experience.

This is what i have in my script.

#!/bin/sh
grep -r 'Windows ASCII' $1
if $(file == "ASCII TEXT");then
echo Windows ASCII
else
echo Something Else 
fi

this is my output:

./fileType.sh: 4: ./fileType.sh: [file: not found

Something Else

#!/bin/sh

grep -r "Windows ASCII" $1
if test "$( file "$1")" = ' ASCII text, with  CRFL line terminators'; then
echo Windows ASCII
else 
echo Something else
fi

my output now is just Something else when the file I am passing in should give an output of Windows ASCII ...

Upvotes: 0

Views: 315

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84579

The actual implementation requires that you interpret/test the result of the file return a bit more. William's answer pointed you in that direction. It is a bit unclear whether you are needing a solutions for traditional shell programming (as in Bourne Shell) or whether you are looking for a Bash (or equivalent) solution. Above, I guess the confusion surrounds the use of:

if test "$( file "$1" )" = 'ASCII TEXT'; then

While this will confirm for you that the file is text with lf separators, exclusive of all others, it does not give you a way to tell whether the file contains lines with CRLF line-ends or not (just that it is not 'ASCII TEXT'). To make the exclusive determination whether the file contains CRLF line-ends, you need to test the file output to find CRLF.

Regardless of the shell, the approach is the same. Capture the result of the file command, and test whether the result contains CRLF. The difference between shells is how you accomplish the test. The following examples provide a way to do the testing the Bourne Shell and the same again in Bash (note: there are many ways to accomplish the test in either, this is just one approach in each):

#!/bin/sh

line=`file -b "$1"`

## Bourne Shell
win=0
for i in $line; do                                # search for CRLF in $line
    if test `expr match "$i" "CRLF"` -gt 0 ; then
        win=1
        break
    fi
done

if test "$win" -eq 1 ; then 
    printf "Windows ASCII\n"
else
    printf "Something else\n"
fi

## BASH
if [[ "$line" =~ "CRLF" ]]; then                  # use substring operator
    printf "Windows ASCII\n"
else
    printf "Something else\n"
fi

Example with/CRLF:

$ ./Type.sh ../../utl/tst/config.win.ini
Windows ASCII
Windows ASCII

Example with/LF:

$ ./Type.sh ../../utl/tst/config.ini
Something else
Something else

Upvotes: 1

William Pursell
William Pursell

Reputation: 212464

Your script is trying to execute a command named "[file". That is not what you want. Offering no advice about the advisability of this solution, but the syntax to implement what you seem to want is:

if test "$( file "$1" )" = 'ASCII TEXT'; then

or

if [ "$( file "$1" )" = 'ASCII TEXT' ]; then 

[ is a command (whether builtin to the shell or external is irrelevant), which is exactly the same as the command test except that it expects its last argument to be ]. It is a heinous kludge that was an attempt to make the syntax appear as if the brackets are tokens in the shell language. IMO, it is far better to use test as it makes it clear that it is not part of the grammar.

Upvotes: 2

Related Questions