Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save name of last file that matches a pattern to variable in bash

Tags:

find

bash

pipe

I refuse to parse ls output, because it is unstable.

First attempt failed with read and find:

read VARIABLE < $(find ./ -type f -name "PATTERN" | sort -r)

But it results ambiguous redirect.

Second attempt failed: it saved /boot file, no idea why, I was not in /:

find ./ -type f -name "PATTERN" | sort -r | read VARIABLE

Third attempt failed: use a subshell:

{ read VARIABLE; } < $(find ./ -type f -name "PATTERN" | sort -r)

No changes.

Finally I achieved, what I wanted:

variable=$(find ./ -type f | sort -r | head -1)

But the solution does not satisfy me, because using head to extract first line seems ugly.
In addition it is highly probable that I would need only second line (what I would get by head -2 | tail -1, I know)

I wonder whether it is possible to use some variation of this:

{ read line1 ; read line2; } < $(find ./ -type f -name "PATTERN" | sort -r)
like image 817
prenc Avatar asked Dec 18 '25 15:12

prenc


1 Answers

The syntax for Process Substitution is wrongly defined it is <() and not <$(). You need to understand that <() places the command output in a temporary file under /var/tmp or a file descriptor /dev/fd/* depending on your OS. To operate on a file with the read command, you need to re-direct its contents with a leading < which puts the contents of the file to the standard input stream of the read command to read the line.

read -r lastfile < <(find ./ -type f -name "PATTERN" | sort -r)

Remember that process-substitution is a bourne again shell feature and not available in the POSIX compliant bourne shell sh.

As far the other attempts are concerned, the one with the pipe would never work

find ./ -type f -name "PATTERN" | sort -r | read VARIABLE

because the VARIABLE is set in the sub-shell from the pipeline, and would never gets propagated to the parent shell. Had you printed it as and when you read it in the child shell, it would have worked.

find ./ -type f -name "PATTERN" | sort -r | { read -r lastfile; echo "$lastfile" ; }

And one with the compound statements involving braces { ;} have the same problem of using incorrect syntax for process substitution which should have been

{ read -r lastfile; } < <(find ./ -type f -name "PATTERN" | sort -r)

and the one with two read commands

{ read -r file1 ; read -r file2; } < <(find ./ -type f -name "PATTERN" | sort -r)
like image 188
Inian Avatar answered Dec 20 '25 17:12

Inian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!