简体   繁体   中英

what does this command mean in bash

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

Although this script seems to be aimed at Git hooks, it has no dependency on Git in any way, so I dropped the and tags. It also has nothing to do with Linux so I dropped the 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.


1 An eval in a shell command makes the shell do various expansions first, then run the command. Where it's useful—eg, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM