Reputation: 997
I have come across a bash script which contains the commands:
cd .git/hooks
[ `eval ls -l | grep -io 'Post-Commit' | wc -l` -eq 1 ] && echo 'post-commit file check... Pass' || echo 'post-commit file check... Fail'
I believe it is to check for a file named post-commit
in the .git/hooks
folder. But even if I create the file post-commit
inside the directory I get the output as: post-commit file check... Fail
.
Am I doing something wrong here? I create my file using:
cat > post-commit
and then I write into it and make it into an executable using chmod +x post-commit
Any help will be really appreciated
Upvotes: 0
Views: 1031
Reputation: 487755
Although this script seems to be aimed at Git hooks, it has no dependency on Git in any way, so I dropped the git and githooks tags. It also has nothing to do with Linux so I dropped the linux tag.
The eval
here is entirely unnecessary.1 We can drop it:
[ `ls -l | grep -io 'Post-Commit' | wc -l` -eq 1 ] &&
echo 'post-commit file check... Pass' ||
echo 'post-commit file check... Fail'
(I broke this into more lines for readability).
As Losko notes in a comment, [
is nominally an external command. In practice it's actually built into most shells, including bash, so that there's no fork-and-exec.
The backquoted section, however, does require a fork-and-exec. Text of the form `command`
is more or less equivalent to code of the form $(command)
. The $(...)
form is generally superior because it provides sane nesting, so if there's a choice of which to use, one should usually prefer the $(...)
form. In any case, it just means: run the command shown and insert its output here. So we're going to run:
ls -l | grep -io 'Post-Commit' | wc -l
as metallic notes in another comment.
The ls -l
does the obvious: a long listing.
The grep -io
has two flags: -i
, meaning ignore case, and -o
, meaning show only the matched part as output. So this is going to look for ls -l
output in which the line contains POST-COMMIT
, post-commit
, pOSt-COMmit
, and so on.
The wc -l
does the obvious: count lines.
The end result is that we count the number of files that have this string in their file name. A file named this-GETS-RUN-post-COMMIThaste-er
for instance gets counted.
The final result of this count gets compared for numeric equality to 1
. If the number is one, the &&
part of the clause is run; if not, the ||
part is run.
Overall, this script fails to do anything useful, because it's too sloppy. It allows mixed-case file names; Git does not. (However, on file systems where the OS allows case-insensitive matching of file names, Git's use of strictly lowercase results in accessing mixed-case or uppercase names after all.) If we find two or more files that match, it complains, yet files whose names simply have a sub-match are probably not an issue here.
1An eval
in a shell command makes the shell do various expansions first, then run the command. Where it's useful—e.g., eval $cmd
—it's also generally pretty dangerous: you must exercise extremely strict control over what goes in $cmd
. Where there are no expansions, as in this case, it's useless. Avoid it as much as possible.
Upvotes: 1