Get the first file of this extension from the folder

I need to get the first file in a folder with the extension .tar.gz . I figured it out:

 FILE=/path/to/folder/$(ls /path/to/folder | grep ".tar.gz$" | head -1) 

but I feel that it can be done easier and more elegant. Is there a better solution?

+11
bash
source share
5 answers

You can get all the files in the array, and then get the desired result:

 files=( /path/to/folder/*.tar.gz ) 

Getting the first file:

 echo "${files[0]}" 

Getting the last file:

 echo "${files[${#files[@]}-1]}" 

You might want to set the nullglob shell nullglob to handle cases where there are no corresponding files:

 shopt -s nullglob 
+16
source share

here is a shorter version from your own idea.

 FILE=$(ls /path/to/folder/*.tar.gz| head -1) 
+4
source share

You can use set as shown below. The shell will expand the wildcard and set will designate the files as positional parameters that can be accessed using $1 , $2 , etc.

 # set nullglob so that if no matching files are found, the wildcard expands to a null string shopt -s nullglob set -- /path/to/folder/*.tar.gz # print the name of the first file echo "$1" 

Using parse ls not recommended, as it will not process filenames containing newlines. In addition, grep not required because you can just do ls /path/to/folder/*.tar.gz | head -1 ls /path/to/folder/*.tar.gz | head -1 .

+3
source share

Here is a way to do it:

 for FILE in *.tar.gz; do break; done 

You tell bash the break loop in the first iteration only when the first file name is assigned to FILE .


Another way to do the same:

 first() { FILE=$1; } && first *.tar.gz 

Here you use the positional parameters of the first function, which is better than set positional parameters of your entire bash process (as with set -- ).

+2
source share

Here is a find based solution:

 $ find . -maxdepth 1 -type f -iname "*.tar.gz" | head -1 

Where:

  • . is the current directory
  • -maxdepth 1 means only checking the current directory
  • -type f means only viewing files
  • -iname "*.tar.gz" means search for any case-insensitive file with the extension .tar.gz
  • . | head -1 | head -1 accepts search results and returns only the first row

You can get rid of | head -1 | head -1 by doing something like:

 $ find . -maxdepth 1 -type f -iname "*.tar.gz" -maxdepth 1 -print -quit 

But I'm actually not sure how portable -print -quit in different environments (although it works on MacOS and Ubuntu).

+1
source share

All Articles