How to pass a filename as a string to awk to parse for destination

662 views Asked by At

TASK

I am trying to pass a pathname/filename to awk in order to take advantage of its field seperator functionality. I want to parse a pathname/filename to see if it is within a user directory in a system. Example paths:

Absolute Paths:

/home/students/username               # VALID
/home/staff/username                  # VALID
/home/students/username/anythingElse  # VALID
/home/staff/username/anythingElse     # VALID
/home/notAccountStorage/anythingElse  # INVALID

Relative Paths (For Exmaple, where the pwd/current is /home/student/user/courseFiles):

../                                       # VALID /home/student/user
../otherDir                               # VALID /home/student/user/other
../.                                      # VALID /home/student/user
../..                                     # INVALID /home/student
../../otherDir                            # INVALID /home/student/otherDir

CODE

My thoughts were to check if the string begins with a '/' then process for absolute path, else process for relative path.

AWK code along the lines of:

awk -F="/" '    BEGIN { directoryAccentCount=0                                                                  \
                        isValid=$FALSE;                                                                         \
                }                                                                                               \
                {                                                                                               \
                        # If the string starts with a "/", path is absolute                                     \
                        if ( $0 ~ /^\// ) {                                                                     \
                                # If either Student/Staff && Number of Fields must be great than 2              \
                                if ( ($2 == "student" || $2 == "staff") && NF > 2 ) isValid=$TRUE               \
                        } else {                                                                                \
                        # Path is relative                                                                      \
                                for (i = 1; i <= NF; i++) {                                                     \
                                        # Count how many directories the User wants to ASCEND towards ROOT      \
                                        if ( $i ~ /\.\./ ) { directoryAccentCount++ }                           \
                                        # If the difference between the Number of Fields and                    \
                                        # the Accent Count is greater than 2, isValid=$TRUE                     \
                                        difference=(NF - $directoryAccentCount)                                 \
                                        if ( $difference > 2 ) isValid=$TRUE                                    \
                        }                                                                                       \
                }                                                                                               \
                END { print $0 ":" $isValid }' << HERE $providedPath
HERE

ERROR

I have tried variations of the above code, but awk keeps attempting to follow the file path, open the file, and process the file's text. I want to process the path itself.

awk: fatal: file `noCopyDir1' is a directory

4

There are 4 answers

1
Matt On

Simplified logic to determine directory ascent/decent only in the case of relative paths. The awk script takes advantage of looping through the fields one by one and returns a negative value when moving towards the root and a positive value when moving away from root.

 # Check that the distance from a User Directory
                set movingDistance = `echo $argPath | awk -F'/' 'BEGIN{                                 \
                        distanceMoved=0                                                                 \
                }                                                                                       \
                {                                                                                       \
                        for ( i=1; i<NF; i++ ) {                                                        \
                                if ( $i ~ /\.\./ ) {                                                    \
                                        distanceMoved--                                                 \
                                } else {                                                                \
                                        distanceMoved++                                                 \
                                }                                                                       \
                        }                                                                               \
                }                                                                                       \
                END {                                                                                   \
                        print distanceMoved                                                             \
                }'`

This is an essential step in determining whether a file path advances outside of user accounts in a system or remains within a user directory, which is how I am applying the script, however, it can be used in many other cases.

2
Ed Morton On

IMHO it's not clear from your question but it sounds like you just want to check if a path given in a file exists or not. That would be:

while IFS= read -r path
do
    [[ -e "$path" ]] && echo "valid" || echo "invalid"
done < file
0
Birei On

You could try with instead of . It can handle paths easily with Cwd and File::stat modules, like:

perl -mCwd=realpath -MFile::stat -E '
    $p = realpath($ARGV[0]); 
    say $p =~ m{\A/home/} && stat($p) ? q|VALID| : q|INVALID|' 
'../../otherDir'

It gets absolute path, checks that it is a home directory and it exists.

0
Jason Hu On

your solution is too complicated. you can do it within one line in bash. there could be solution shorter than mine:

[ -d "$(readlink -f $YOUR_PATH | awk -F/ '$2 == "home" && $3 != "" {print "/"$2"/"$3}')" ]

explanation:

readlink -f $YOUR_PATH

this converts whatever path to a absolute one.

awk -F/ '$2 == "home" && $3 != "" {print "/"$2"/"$3}'

since the path is absolute already, so i can directly extract the first two path out, but restrict it's under home folder and it's under some subfolder too.

then just check to see if it's a folder.