简体   繁体   中英

How to detect if a file is a folder in bash script on macOS?

I have created a macOS Service with Automator which actually will attach every file from the Finder to a new Thunderbird compose window and is just a simple bash script.

    for f in "$@"
do
        open -a /Applications/Thunderbird.app/ "$f"
done

This Service also would work for any folder, but for sure you can not attach a folder to a compose window. But my idea is now to let the script detect if the file is a document or a folder. If it is a document, attach it. If it is a folder, first zip compress it and than attach it. In the way:

if file is folder than
// zip compress folder
// attach *.zip to Thunderbird compose window
else // seems to be a document
// attach document to Thunderbird compose window

But how do I detect if the file is a folder and than compress it as zip file in the bash script?

if [[ -d "$file" ]]; then
  # do your thing for the directory
else
  # do the other thing for the file
fi

For more details, please see this related question: How do I tell if a regular file does not exist in Bash?

Code:

#!/bin/bash
if [ -d "$f" ]; then
    upload_file="$f.zip"
    # zip compress folder
    zip "$f.zip" "$f"
elif [ -f "$f" ]; then # seems to be a document
    upload_file="$f.zip"
else # Unknown file type
    echo "Unknown file type." 1>&2
    exit 1
fi
# attach file to Thunderbird compose window
open -a /Applications/Thunderbird.app/ "$upload_file"
exit 0

Explanation:
In bash "folders" are referred to as "directories." You should checkout the man page on test.

$ man test

The relevant section for you is:

NAME
 test, [ -- condition evaluation utility

SYNOPSIS
 test expression
 [ expression ]

...

 -d file       True if file exists and is a directory.

 -e file       True if file exists (regardless of type).

 -f file       True if file exists and is a regular file.

To test if a file is a directory:

test -d "$f"

OR

[ -d "$f" ]

To test if a file is a regular file:

test -f "$f"

OR

[ -f "$f" ]

Edit: Quoted variables in sample code to avoid globbing and word splitting.

This command [ -f "$filename" ] will return true for files, while [ -d "$dirname" ] will return true for directories.

I would suggest using a check for file as well, because you could have things that are neither directories nor files.

I would approach it this way:

if [ -d "$fileDirectory" ]; then myCommandDirectories;
elif [ -f "$fileDirectory" ]; then myCommandFiles;
elif [ -z "$fileDirectory" ]; then myCommandEmptyArgument;
else myCommandNotFileDirectory; fi

On the code above, the syntax if [ -d ... ] would test if the argument is a directory , the syntax if [ -f ... ] would test if the argument is a file , the syntax if [ -z ... ] would test if the argument is unset or set to the empty string , and if the argument is none of those, you could still execute a certain command/script (in the exemple above myCommandNotFileDirectory ).

Note : I included checking for an empty string, even if that was not asked on the question, because this is a "quality/error" control test I would normally do -- the variable "$fileDirectory" should never be empty on this context, and if it is, I would like to know that (it would show me that the script is not working properly), and thus I normally would redirect that command to a log file, like this:

elif [ -z "$fileDirectory" ]; then somecommand && echo "empty fileDirectory string ocurred" >> /var/log/mylog;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM