DJ did explain it, but it can be confusing at first.
With logical OR, only one of the subconditions needs to be true for the entire proposition to be true. Most computer languages (possibly all) test OR’d conditions in the order they’re presented until one of them turns out to be true or the last test returns its result. If a true result comes up, there’s no need to test any of the following conditions, so true is returned for the entire OR’d group at that point. Only if a condition proves false is the next test (if any) carried out.
The bash trick here is a sleight-of-logic based on this. If the folder exists, the test for it returns true and the script doesn’t bother executing the statement after the OR (||). If the folder doesn’t exist, the false result causes the script to try again with what it believes is another test, but which is in fact the creation of the folder. This also returns a true or false result in bash, so the script doesn’t get confused.
Conversely, with logical AND (&&), conditions are tested in the order presented until one of them turns out to be false.
But why bother checking if the folder exists (or doesn’t) at all? As I said somewhere above, if you use mkdir’s -p option, it’ll create the folder if it doesn’t exist and not error if it does.
There is actually one difference between this and checking for the folder’s existence first which could be important. Using the -p and -m options together imposes the specified permissions even where the folder already exists with different permissions. You may not always want this.
I wouldn’t say more obvious, I would say it’s more common. It’s personal preference because the if-statement cannot be written down like you wrote it down. In bash an if-statement would look like
[format]if [[ ! -d theFolder ]]
then
mkdir.
fi
[/format]
if you want to write it down as compressed as possible it would look like:
[format]if [[ ! -d theFolder ]];then
mkdir.;fi[/format]
So I think that especially compared to the last compressed example that using OR is more “obvious” than using NOT.
Update: here another example to check if a file exists and return an to boolean coercible string.
set fileExists to (do shell script "if [[ -e " & quoted form of theFile & " ]]
then
echo yes
else
echo no
fi") as boolean
in a more compressed way:
set fileExists to (do shell script "if [[ -e " & quoted form of theFile & " ]]; then
echo yes; else
echo no; fi") as boolean
Or when using the AND and OR operator:
set fileExists to (do shell script "[[ -e " & quoted form of theFile & " ]] && echo yes || echo no") as boolean
To me the last one with the AND and OR operator is the easiest to read. But like I said, it’s more like a personal preference rather than one being better than the other.
Nigel, you seem to be feeding us one partial piece of critical information at time.
If I had known when you first suggested using the -p switch with mkdir that it changes permissions on existing directory, then I would NOT have considered it at all.
Knowing that now eliminates using your suggestion.
I appreciate your help, but in the future if there are potentially adverse side effects to a suggestion you are making please tell us about it up front. This especially applies to lesser known scripts like shell scripts. Had I not pursued many follow-up questions about mkdir, I, and probably many other readers, would have not realized this issue.
IMO, using the (A OR B) syntax to execute B only IF A is false is a more advanced technique, and may not be easily recognized by a large number of scripters.
The most clear syntax (IMO) for creating a new directory (folder) IF it does not already exist is:
EDIT: 2016-04-04 14:01 CT
### This revised script corrects errors in DJ's syntax, and provides complete script, which I have tested ###
set newFolderPath to quoted form of (expandPath("~/Documents/Test/NewFolder"))
set cmdStr to "if [[ ! -d " & newFolderPath & " ]]; then
mkdir -m 755 " & newFolderPath & "; fi"
do shell script cmdStr
on expandPath(pPathStr)
local fullPath
set fullPath to pPathStr
if fullPath = "~" then
set fullPath to (POSIX path of (path to home folder))
else if fullPath starts with "~/" then
set fullPath to (POSIX path of (path to home folder)) & text 3 thru -1 of fullPath
end if
return fullPath
end expandPath
where
newFolderPath is the quoted form of the full POSIX path to the folder.
! is logical NOT
-d is a bash conditional expression that returns TRUE if the folder exists
-m 755 is the mkdir switch to set permissions on the folder to read, write and execute by the owner, read and execute by group members, read and execute by others, and no set-uid or set-gid behaviour
OR you can use this syntax which makes use of the formulation:
(A OR B)
execute B only if A is false
Look out, JMichaelTX. There are potentially adverse side effects to everything about computer scripting and programming, whether suggested by me or anyone else. It’s up to you to evaluate and test any information you receive to make sure it’s suitable for your purposes. No-one here is expected to second-guess or take responsibility for their advice being used for any purpose other than the one for which it’s intended.
In this thread, the OP wrote:
And later:
The clear implication is that if the folder exists, it’s because it’s already been created for the same purpose and already has its permissions set for that purpose. My -p suggestion is 100% in accordance with that.
I can’t see anything in your posts above which suggests you might not want the permissions set if the folder already exists. You only ask for an explanation of the logic in the bash script.
I did point out as an afterthought, when it occurred to me, that the -m option is still operative even when the folder already exists ” it’s an easy thing to check for yourself ” but it was more for the benefit of later readers that from any inkling that your requirements were different from the OP’s.
That’s a nice CYA statement.
Given your reputation, sir, I expected more from you. Consider lesson learned.
I agree that each person has to take full responsibility for using any suggestions or code received from a post on an Internet forum, and to fully understand and test before using.
Having said that, my personal ethics are that if I know of a side effect or adverse result of using something that I am suggesting, then I feel compelled to advise the reader of that. If you choose to throw out suggestions for unsuspecting users without providing any warnings that your already know about, then that is up to you sir.
I surely don’t have to tell you that these threads are for the benefit of all users, not just the one who made the original post. I’m sure you know that other users in search of answers will come along later, and use what they find.
In the case of mkdir is hard to know even where to find documentation if you are not an experienced shell scripter.
Given that the discussion at the time was about testing for an existing folder, you suggested a method that does not just test for the folder, but also sets permissions if the folder does exist. So at the best, IMO, that was bad advice. I still feel that you should have advised us at the time of the suggestion that it also sets permissions.
Which I did on purpose I though the ‘.’ character speaks for itself.
update: comment on expanding path. Since bash is quite new for you by default the tilde is replaced by the home directory but it can contain a path to any folder. That’s because the tilde is an environment variable.
You don’t need a space behind a ‘;’, it’s an habit I do for better readability when I write shell scripts. The space behind theFolder is the only mistake I have corrected, I have not tested the code and wrote it quickly, my apologies.
Sometimes it’s better safe than sorry and, yes, bash is sensitive to spaces. Every operator and primary should be surrounded by spaces. To fit all different notations here to make it clear what and what you cannot do in bash.
set fileExists to (do shell script "if [[ -e " & quoted form of theFile & " ]];then echo yes;else echo no;fi") as boolean
But it makes readability worse and probably no Bash scripter, beginner or amateur, would choose that over AND and/or OR operators and definitely experienced ones not. When someone asks a one liner if statement the logical operators are used in Bash. Keep in mind that I do prefer the Bash scripts in do shell script written in a more Bash style than considering AppleScript style, so that only speaks for myself.
DJ, maybe you’ve been programming in Bash so long that the (A OR B) technique seems more natural to you, and that’s fine. But I don’t think you can assume that “no bash scripter, beginner or amateur, would choose that over AND and/or OR operators”, because I’m at least one who would.
When I’m reading a language I am not very familar with, use of the “IF/THEN” construct is very clear, and sends an immediate signal to me that this statement is an IF test.
When I see (A OR B), especially when it is used with other strange (to me) syntax like:
do shell script "[[ -d " & folderPath & " ]] || mkdir -m 755 " & folderPath
then I have to stop, and figure out what is really going on here. Add to that, that there are many different symbols for logical OR.
So, IMO, use of IF/THEN is must easier to read than (A OR B).
But we each have our own preferences, and experiences.
Sure, and it’s also a preference of mine because one is not better than the other. To be clear, I’m not trying to convince you to use otherwise, just showing all the different forms on how to write an if-statement down in Bash. It’s yours to pick the notation you like most.