2

With the following content in the clipboard:

curl "foo" --compressed ;
curl "bar" --compressed ;
curl "baz" --compressed ;

The following command creates one line for each clipboard-line:

pbpaste | awk '{"pwgen 10 1" | getline pass; print substr($0, 1, length($0) -1) ">>myfile-" pass ".jpg"}'

generating the output below:

curl "foo" --compressed >>myfile-du7EeHegh7.jpg
curl "bar" --compressed >>myfile-du7EeHegh7.jpg
curl "baz" --compressed >>myfile-du7EeHegh7.jpg

Question:

The issue here is that pwgen 10 1 seems to be executed only once at the beginning, while I'd like it to be executed for every new clipboard line, hence generating a new unique filename for each line. How to make sure that this call to pwgen is repeated and not only executed once at the beginning?

Desired output:

# each filename is unique
curl "foo" --compressed >>myfile-zus83j10ai.jpg
curl "bar" --compressed >>myfile-nbjfo2pa9d.jpg
curl "baz" --compressed >>myfile-ahqdugpo90.jpg
2

when using external command in awk and using getline from a Pipe, better to assign the command into a variable like my_command="my external command here" and call it with my_command |getline to_save that later you should close(my_command) it in order to make output distinct for every run; it's also suggested to do a close(my_command) in BEGIN{...} block to ensure no command is open for the my_command.

additionally do testing on the getline return code and proceed if it only was succeed; so you will have to do:

pbpaste |awk 'BEGIN{ close(cmd); }
{ cmd="pwgen 10 1";
  if (cmd | getline pass) {
      print substr($0, 1, length($0) -1) ">>myfile-" pass ".jpg";
      close(cmd);
  } else { print "running command failed!"; exit 1; }
}'

However with above if the command itself failed, getline still will be return success return-code since we don't check command success/failure, to put test on command status we can do:

pbpaste |awk 'BEGIN{ close(cmd); }
{ cmd="pwgen 10 1 || echo failed";
  if ((cmd | getline pass)>0 && pass!="failed") {
      print substr($0, 1, length($0) -1) ">>myfile-" pass ".jpg";
      close(cmd);
  } else { print "running command failed!"; exit 1; }
}'

quote from manual:

If the same file name or the same shell command is used with getline more than once during the execution of an awk program (see section Explicit Input with getline), the file is opened (or the command is executed) the first time only. At that time, the first record of input is read from that file or command. The next time the same file or command is used with getline, another record is read from it, and so on.

from the above link Explicit Input with getline mentioned:

The getline command returns 1 if it finds a record and 0 if it encounters the end of the file. If there is some error in getting a record, such as a file that cannot be opened, then getline returns -1. In this case, gawk sets the variable ERRNO to a string describing the error that occurred.

see also:

3
  • 1
    You should also test that the call to getline succeeded before using the value of the variable that you hope it populated (pass), see awk.freeshell.org/AllAboutGetline. – Ed Morton Feb 9 '20 at 22:50
  • @EdMorton yes, updated answer to mention that. thanks – αғsнιη Feb 10 '20 at 7:30
  • getline returns 0 on eof, <0 on error, >0 on success. close() returns with the exit status of the command. – Stéphane Chazelas Feb 10 '20 at 12:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.