14

I want to write a script to find a file with specific extension.this much i have done:

#!/bin/bash
file="/home/Savio/Dsktop/check/*.csv"
file1="/home/Savio/check/*.txt"
if [[ -f "$file" && -f "$file1" ]];
then
    echo " found."
else
    echo "not found."
fi

Where the check folder contains sub-folders. Please correct me if anything wrong is there

5 Answers 5

7

If you don't want recursion, you can do

export DIR=/home/Savio/Dsktop/check
if ls ${DIR}/*.txt &>/dev/null && ls ${DIR}/*.csv &>/dev/null
then
    echo "Found."
else
    echo "Not found."
fi

Or, in perl:

perl -e '
    $DIR="/home/Savio/Dsktop/check";
    @a= glob "${DIR}/*.txt";
    @b= glob "${DIR}/*.csv"; 
    print  @a && @b ? "Found.\n" : "Not found.\n"
' 

If you do want recursion, the solution proposed in the other answers will work. You can make it go faster by making find stop after the first match it finds:

export DIR=/home/Savio/Dsktop/check
CSV=$(find "$DIR" -name *.csv|head -n1)
TXT=$(find "$DIR" -name *.txt|head -n1)
[ ! -z "$CSV" ] && [ ! -z "$TXT" ] && echo Found || echo Not found

References

2

bash script to check whether csv files exists and for loop all of them of exists

#!/bin/bash
# count variable to check if csv files exists in current directory
count_file=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count_file != 0 ]
then 
  for file in *.csv; do
    echo ${file##*/}
  done
fi 
1
  • I upvoted for usefulness, BUT actually, it deserves a minus 1 because you mistyped your code May 25, 2022 at 16:57
2

The wildcard in file1 is never expanded because it's always in quotes.

In bash, one way is to set the nullglob option so that a wildcard that matches no file expands to an empty list.

#!/bin/bash
shopt -s nullglob
csv_files=(/home/Savio/Dsktop/check/*.csv)
txt_files=(/home/Savio/check/*.txt)
if ((${#csv_files[@]} && ${#txt_files[@]}))
then
  echo " found."
else
  echo "not found."
fi

If you want to match dot files as well, set the dotglob option.

With only a POSIX shell, you need to cope with the pattern remaining unchanged if there is no match.

matches_exist () {
  [ $# -gt 1 ] || [ -e "$1" ]
}
if matches_exist /home/Savio/Dsktop/check/*.csv &&
   matches_exist /home/Savio/check/*.txt; then
  echo " found."
else
  echo "not found."
fi

Note that it looks for files regardless of their type (regular, directory, symlink, device, pipe...) while your [[ -f file ]] checks whether the file exists and is a regular file or symlink to regular file only (would exclude directories, devices...).

1
  • "With only a POSIX shell, you need to cope with the pattern remaining unchanged if there is no match." you said something important there May 25, 2022 at 16:50
1

find would probably work better here.

csv=$(find /home/Savio/Dsktop/check -type f -name "*.csv")
txt=$(find /home/Savio/check/ -type f -name "*.txt")

What you have will not recurse into sub-directories.

1

Be aware that if [[ -f "$file" ]] will fail if $file contains more than one filename -- which is likely to happen when you are selecting the file using a wildcard.

You should either check for a specific filename (without any wildcards) or use Petey T's approach and check if the number of files found by find is greater than 0:

csv=$(find /home/Savio/Dsktop/check -type f -name "*.csv")
txt=$(find /home/Savio/check/ -type f -name "*.txt")
if [[ ( -n $csv ) -a ( -n $txt ) ]]
then
    echo "found"
else
    echo "not found"
fi
4
  • 1
    Actually, wildcards aren't expanded into globs inside [[ see Greg's wiki
    – Joseph R.
    Aug 20, 2013 at 17:02
  • To make your if condition POSIX-compliant, you can do if [ ! -z $csv ] && [ ! -z $txt ]...
    – Joseph R.
    Aug 20, 2013 at 17:23
  • 1
    Wildcards aren't expanded inside [[ but the wildcard will be expanded when file and file1 are set.
    – doneal24
    Aug 20, 2013 at 17:42
  • @DougO'Neal Right you are. My bad...
    – Joseph R.
    Aug 20, 2013 at 17:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .