简体   繁体   中英

bash: syntax error near unexpected token `|'

This command works well in command prompt :

 ]$ ls -ltr ../cmxserver.log*|grep "`date | awk '{print $2" "$3}'`"|cut -d "/" -f2
 cmxserver.log.2
 cmxserver.log.1
 cmxserver.log

However, using this in for loop gives error bash: syntax error near unexpected token `|'

   ]$for y in `ls -ltr ../cmxserver.log*|grep "`date | awk '{print $2" "$3}'`"|cut -d "/" -f2`

 -bash: syntax error near unexpected token `|'

Any idea ?

Thanks

The whole line can be solved by find command:

find .. -maxdepth 1 -mtime -1 -daystart -name 'cmxserver.log*' -printf "%f\n"
  • .. - directory where to search
  • -maxdepth 1 - don't go recursive to subdirectories
  • -mtime -1 - only today's files
  • -daystart - count the day since midnight, not last 24 hrs
  • -name 'cmxserver.log*' - filenames
  • -printf "%f\\n" - print only basename

You probably understood what you meant when you typed:

for y in `ls -ltr ../cmxserver.log*|grep "`date | awk '{print $2" "$3}'`"|cut -d "/" -f2`

But you have managed to completely confuse bash. Bash (and other shells) don't nest backticks ( ` ) unless the inner ones are backslashed. As written, the second backtick is considered to close the first one, resulting in the command ls -ltr ../cmxserver.log*|grep " . Since you did not put a space before date , the word date is parsed as part of the word including the command substitution. Similarly, the single-quoted '{print $2"$3}' is parsed as being prepended to the backticked command "|cut -d "/" -f2 .

Of course, both of those backticked commands are syntax errors because they contain unclosed double quotes, but before bash reaches the point of parsing and executing the commands, it is left with something which roughly speaking looks like:

for y in word1 | awk word2

which is a syntax error because the pipe symbol can only appear between complete commands, and for y in word1 is not a complete command.

Backticks are deprecated. Stop using them.

If you had written:

   for y in $(ls -ltr ../cmxserver.log* |
              grep "$(date | awk '{print $2" "$3}')" |
              cut -d "/" -f2)

both bash and human readers would have found the expression much easier to parse, and bash would have parsed it as you expected.

Having said that, it is never a good idea to try to parse ls output, and it is never necessary to parse date output because you can specify a format string; in this case, you could have used date +"%b %d" to get the month and day. (First link courtesy of a comment by Charles Duffy.)

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