I’ve recently enrolled in a cybersecurity bootcamp and am having a little trouble figuring out where I’m going wrong writing this script with a grep command. I’m supposed to be pulling employee names from a schedule and the script is supposed to be able to accept 2 arguments representing a specific date and a specific time.
If I type the following line below, it successfully goes into the schedule file with the date of 0310 and pulls the name of the employee that was working at 5am.
find -type f -iname *0310* | grep "05:00:00 AM" ./* | awk -F" " '{print $5, $6}'
However when I turn it into a script like this:
#!/bin/bash
find -type f -iname *$1* | grep $2 ./* | awk -F" " '{print $3, $4}'
And execute like this:
./script.sh 0310 "05:00:00 AM"
It gives me the following error code of the following and prints the employees who were working at 5am and also 5pm.
grep: AM: No such file or directory
I also get this error if I have another file with "0310" in the name
find: paths must precede expression:
random_file_with_0310.txt' find: possible unquoted pattern after predicate
-iname’?
Where am I going wrong with this script? Very new to BASH
2
Answers
I think what you actually want is:
Note that
awk
by default uses any number of whitespace (spaces, tabs) as a separator, so your field-separator may not actually be what you need/want, either.And a different approach:
Slightly shorter (less typing), but more processes involved.
You first problem is quoting.
This is because what
grep $2 ./*
is running ismaking
AM
the file argument, followed by the expansion of./*
which is every file in whatever directory you ran the command from, which is also not what you want. You quoted it correctly in your CLI example, but you have to quote it in your script.This will pass the "5:00:00 AM" correctly, but isn’t going to search for it in the file(s) returned from
find
.Assuming there is only one file (I wouldn’t, but for simplicity’s sake…) – try
Personally, I prefer the improved syntax for the same thing –
If there is any chance you are going to get multiple files, then this is likely way beyond the scope of a bootcamp unless they are really doing it right, in which case c.f. this discussion of why filenames are not to be trusted.
ANYWAY – once you have your filename, you still don’t need
grep
.or even, in one step,
…but if you just felt the need to add a redundant pattern parser antipattern, then
A possible alternative, with no promises on performance…
Call it with
This should let the interpreter locate matching files for you and pass that list to the script.
awk
itself will only open the files it is passed as arguments, so you no longer need thefind
.awk
can also pattern match for lines in those files, so you no longer need the separategrep
.(This does run the possibility of returning directories and other weirdness as well as just plain files; we can add lines to accommodate that, but I’m trying to keep it fairly simple for the given problem.)
I omitted the
-F" "
– you probably don’t need that, but be sure to test to see if it changes your actual output dataset. If what you literally meant was that you want every space to delimit a field, so that consecutive spaces mean empty fields, use-F'[ ]'
.If that’s too fancy for your context, tink’s answer is probably what you want.