Files test How to recover a specific variable

Hi everyone !:wink:

I'm Arnaud and I'm new on this forum, I begin in the Shell. Let me explain, I want to test the presence of file, so far so good. Below, my code :

if [ -e "$fichier1" ] && [ -e "$fichier2" ] && [ -e "$fichier3" ] ; 
then 
        Pgsql ; 
else 
        echo \nLe fichier $fichier n\'existe pas ; 

I would like to recover in a variable $fichier, only the file doesn't exist. I want to it like that to avoid many "if" Can you help me please. Sorry for my english, I begin also :smiley: :slight_smile:

Try:

for fichier in fichier1 fichier2 fichier3; do
  if [[ -e ${fichier} ]]; then
        Pgsql
  else
        echo \nLe fichier ${fichier} n\'existe pas ;
  fi
done
1 Like

Thank you for your quick reply, that work fine :b:

What is the desired result, if more than one file does not exist? Should fichier then be an array holding the names of these files?

Hi rovf, Below this is my desired result for example :

if [ -e "$fichier1" ] && [ -e "$fichier2" ] && [ -e "$fichier3" ] ; 
then
        Pgsql ; 
else
        echo \nLe fichier $fichier1 has not been found ; or echo \nLe fichier $fichier2  has not been found or echo \nLe fichier $fichier3  has not been found

I would like that the output me says only the file that not exist.. sorry if I am not very clear

Well, from a linguistic point of view, when listening exactly the non-existing files, the connection word should not be or, but and, but anyway: In this case you have two choices: Output the missing bits piece by piece, or collect everything into one array and output the result afterwards. I would go for the latter. Here is a sketch of the program:

declare -a missing 
for name in $fichier1 $fichier2 $fichier3 ....
do
     [[ -e $name ]] || missing[${#missing
[*]}]=$name
done

if (( ${#missing
[*]} == 0 ))
then
    Pgsql
else
    echo "Missing: " ${missing
[*]}
fi
1 Like

Thank you for the very good answer, you help me a lot! For me the post is solved. :b::b::b::b: :slight_smile:

Hi all !:slight_smile:

I reopens the post because I still have a few questions concerning my script that it below :

declare -a missing
for name in $fichier1 $fichier2 $fichier3 $fichier4 $fichier5 $fichier6
do
        [[ -e $name ]] || missing[${#missing[*]}]=$name
done

if (( ${#missing[*]} == 0 ))
then
        echo -e "\nDate :   $date_form2\nFile :   $name_files\nHeight : $height_files\n"
        echo -e "Date :   $date_form2\nFile :   $name_files1\nHeight : $height_files1\n"
        echo -e "Date :   $date_form2\nFile :   $name_files2\nHeight : $height_files2\n"
        echo -e "Date :   $date_form2\nFile :   $name_files3\nHeight : $height_files3\n"
        echo -e "Date :   $date_form2\nFile :   $name_files4\nHeight : $height_files4\n"
        echo -e "Date :   $date_form2\nFile :   "$name_files5"\nHeight : $height_files5"
else
        echo "Missing: " ${missing[*]}
fi
        echo -e "\nDisk Used : $disk_used\nDisk Available : $disk_available\nDisk Used In Percent : $disk_percent\n"

exit 0

here, It work like I want but in the "else" section I would like the same thing that in the "then" section but with the path of missing file instead of the "$name_fileX".

I would like this ouput for example (file5 missing):

Date :   2016-09-19
File :   name_files
Height : 100K

Date :   2016-09-19
File :   name_files1
Height : 160K

Date :   2016-09-19
File :   name_files2
Height : 4.0K

Date :   2016-09-19
File :   name_files3
Height : 236K

Date :   2016-09-19
File :   name_files4
Height : 4.0K

Date :   2016-09-19
File :   Missing: name_file5
Height : 4.0K

Disk Used :  39M
Disk Available : 185M
Disk Used In Percent : 18%

Here, While hoping to have been clearly....:o thanks by advance :b::slight_smile:

Please try this & modify as per your need. Iterate through the array missing in else part .

for missing_filename in "${missing[@]}"; do
echo "$missing_filename"
done

I can't see the correlation between e.g. fichier2 and name_files3 . Should there be any, why don't you do the output right in the for loop?

I tried to write an example clearer:

date_form1=$(date +'%y-%m-%d') # Variable date format : YYMMDD
date_form2=$(date +'%Y-%m-%d') # Variable date format : YYYYMMDD

height_file1=$(du -h /home/$date_form2/* | sed -n '1p' | cut -c 1-4)
name_file1=$(du -h /home/$date_form2/* | sed -n '1p' | cut -c 6-)

height_file2=$(du -h /home/$date_form2/* | sed -n '2p' | cut -c 1-4)
name_file2=$(du -h /home/$date_form2/* | sed -n '2p' | cut -c 5-)  

height_file3=$(du -h /home/$date_form2/* | sed -n '4p' | cut -c 1-4)
name_file3=$(du -h /home/$date_form2/* | sed -n '4p' | cut -c 5-) 

height_file4=$(du -h /home/$date_form1/* | cut -c 1-5) 
name_file4=$(du -h /home/$date_form1/* | cut -c 6-) 

height_file5=$(du -h /home/$date_form1/* | cut -c 1-5)
name_file5=$(du -h /home/$date_form1/* | cut -c 6-) 

height_file6=$(du -h /home/file6-$date_form1.tar.gz | cut -c 1-5) 
name_file6=$(du -h /home/file6-$date_form1.tar.gz | cut -c 6-) 

disk_used=$(df -h | sed -n '9p' | cut -c 23-27)
disk_available=$(df -h | sed -n '9p' | cut -c 29-33)
disk_percent=$(df -h | sed -n '9p' | cut -c 35-38)

fichier1="/home/$date_form2/file1" 
fichier2="/home/$date_form2/file2"
fichier3="/home/$date_form2/file3"
fichier4="/home/$date_form1/file4"
fichier5="/home/file5-$date_form1.tar.gz" 
fichier6="/home/$date_form1/file6" 

affiche () {
if [ $name == "$fichier1" ];
then
	: (I wish nothing, No display)
else
	echo -e "\nDate :   $date_form2\nFile :   $name_file1\nHeight : $height_file1\n" ;
fi

if [ $name == "$fichier2" ];
then
	: (I wish nothing, No display)
else
	echo -e "Date :   $date_form2\nFile :   $name_file2\nHeight : $height_file2\n" ;
fi

if [ $name == "$fichier3" ];
then
	: (I wish nothing, No display)
else
	echo -e "Date :   $date_form2\nFile :   $name_file3\nHeight : $height_file3\n" ;
fi

if [ $name == "$fichier4" ];
then
	: (I wish nothing, No display)
else
	echo -e "Date :   $date_form2\nFile :   $name_file4\nHeight : $height_file4\n" ;
fi

if [ $name == "$fichier5" ];
then
	: (I wish nothing, No display)
else
	echo -e "Date :   $date_form2\nFile :   $name_file5\nHeight : $height_file5\n" ;
fi

if [ $name == "$fichier6" ];
then
	: (I wish nothing, No display)
else
	echo -e "Date :   $date_form2\nFile :   "$name_file6"\nHeight : $height_file6" ;
fi

}

declare -a missing
for name in $fichier1 $fichier2 $fichier3 $fichier4 $fichier5 $fichier6
do
     [[ -e $name ]] || missing[${#missing[*]}]=$name
done

if (( ${#missing[*]} == 0 ))
then
	echo -e "\nDate :   $date_form2\nFile :   $name_file1\nHeight : $height_file1\n" ;
	echo -e "Date :   $date_form2\nFile :   $name_file2\nHeight : $height_file2\n" ;
	echo -e "Date :   $date_form2\nFile :   $name_file3\nHeight : $height_file3\n" ;
	echo -e "Date :   $date_form2\nFile :   $name_file4\nHeight : $height_file4\n" ;
	echo -e "Date :   $date_form2\nFile :   $name_file5\nHeight : $height_file5\n" ;
	echo -e "Date :   $date_form2\nFile :   "$name_file6"\nHeight : $height_file6" ;
else
          
	affiche ;
	echo -e "\n\nMissing: " ${missing[*]}

fi

	echo -e "\nDisk Used : $disk_used\nDisk Available : $disk_available\nDisk Used In Percent : $disk_percent\n" ;

exit 0 ;

Its output :

Date :	2016-09-19
File :  /home/16-09-19/file1
Height : 100K

Date :	2016-09-19
File :  /home/16-09-19/file2
Height : 160K

Date :	2016-09-19
File :  /home/16-09-19/file3
Height : 4.0K

Date :	2016-09-19
File :  /home/16-09-19/file4
Height : 236K

Date :   2016-09-19
File :
Height :

Missing:  /home/16-09-19/file6

Disk Used :  39M
Disk Available : 185M
Disk Used In Percent : 18%

I took off the file 6 for provoke the function "affiche", like you note, it misses display of the file 5 and on position of file 6 it's blank.

Me, I would like :

Date :   2016-09-19
File :  /home/16-09-19/file1
Height : 100K

Date :	2016-09-19
File :  /home/16-09-19/file2
Height : 160K

Date :	2016-09-19
File :  /home/16-09-19/file3
Height : 4.0K

Date :	2016-09-19
File :  /home/16-09-19/file4
Height : 236K

Date :	2016-09-19
File :  /home/16-09-19/file5
Height : 236K

Missing:  /home/16-09-19/file6

Disk Used :	39M
Disk Available : 185M
Disk Used In Percent : 18%

or

Date :	2016-09-19
File :  /home/16-09-19/file1
Height : 100K

Date :	2016-09-19
File :  /home/16-09-19/file2
Height : 160K

Date :	2016-09-19
File :  /home/16-09-19/file3
Height : 4.0K

Date :	2016-09-19
File :  /home/16-09-19/file4
Height : 236K

Date :	2016-09-19
File :  /home/16-09-19/file5
Height : 236K

Date :	2016-09-19
File :  Missing:  /home/16-09-19/file6
Height : 


Disk Used :  39M
Disk Available : 185M
Disk Used In Percent : 18%

I hope I have helped you :confused:

As for displaying the full path, you have two choices: If you know that the file names are always relative pathes, the easiest is to prepend $PWD/. If this is not the case, or if you want to have the path "cleaned up" by not containing .. elements, you need to convert it to an absolute path explicitly. Google for "how to convert a relative path to an absolute path".

Aside from this, the logic of your script is flawed. You obviously want to treat each file separately, i.e. create for each file some information, whether it is missing or not. You have (at least) two choices to achieve this:

The first ist to output the desired information INSIDE the if-block where you detect that the file is missing. The second one - if, for whatever reason, you want to keep problem DETECTION and problem REPORTING separate, I suggest a completely differnt approach:

Either use two arrays (one containing all the file names, and one containing a code for the problem occuring with each corresponding file, for instance "missing" or "ok"), or alternatively use only one associative array, where the key is the file name and the value is "missing" or "ok".

---------- Post updated at 08:58 AM ---------- Previous update was at 08:50 AM ----------

I just noticed - by re-reading your initial post - that you never indicated which shell you are using, so some of the suggestions (such as associative arrays) I gave might not work in your shell.

Hence, the first step would be that you decide on a certain shell language, before we can discuss, how exactly a problem can be solved.

Common language choices are:

  • POSIX shell (most unconvenient to program, but maximum compatibility - this is often used by system administrators who have to manage a network of different Unix flavours or different shell versions)

  • bash (chances are highest that, if you ask a colleague, s/he will know it)

  • Zsh (IMO most convenient for shell programming)

  • ksh (Many people like it; I can't comment on it, because of lack of experience)

I use for most of my shell programming Zsh, because it is really made for programmers, but bash is also a very popular choice.

Thank for your reply, I use #!/bin/bash , So I work in Bash ? I'm beginner, I'm open at all.what do you recommend?

Why don't you try something along this line:

for name in $fichier1 $fichier2 $fichier3 $fichier4 $fichier5 $fichier6
  do if [ -e $name ]
         then 	echo -e "Date :   $date_form2\nFile :   $name_file2\nHeight : $height_file2\n" ;
         else 	echo -e "\n\nMissing: " $name
     fi
  done

Because my problem concerning the display

Because my script does what I want, but it does not appear what I want.

This depends on how you invoke your script.

If the script as executable rights, and you invoke it by typing the script name, the #! line defines, which language processor will be used to run your script. In your case, it is the bash executable stored in the /bin directory.

Alternatively, you can invoke the language processor to be used explicitly from the command line. For instance, if I write bash myfile , the file myfile should better be a bash script (and not zsh or ksh or awk....), as it will be executed under bash. The same applies to other languages - zsh, perl, ruby, ....

Now as for the recommendation. It is difficult to give a recommendation without starting a language war, because most programmers seem to be very picky when it comes to choosing one language over another, and everyone has his favorite pet, so note that I give here only my personal opinion, and others might advice you differently.

As for shell programming, after having had long experience with bash and a little bit experience with ksh, csh and tcsh, I turned to zsh, because I found that quite a few things are simpler to do in zsh than in the other languages. I yet have to see something which is easier to do in bash than in zsh (there must be something). The main drawback of zsh is that fewer people use it, so if you get stuck, you might have to search longer for someone to help. However, I got every zsh question answered by someone so far.

As second language, I tend to use Ruby (after having collected experience with awk, Perl, Python and Tcl), because I found it more expressive than the others and much easier to learn.

Of course one thing to consider it, where your script will run, and how much control you have on the software at the target machine. If I know that there is no zsh installed on the target machine, and I don't even have an account there, it would not be wise to deliver a zsh script. Having said this, even when using bash, you should make sure that you either develop your scripts with the same bash version than the one available on the target host, or write your scripts in a way that they will likely run under each version. This might turn out to be difficult, in particular for someone who doesn't have much experience yet.

If you run your programs only on your own machine, it is up to you what tools you choose.

Thanks for your experience Rovf, me concerning, I continue to work on this script and when I find the solution, I post it.