I have wrote a command to only mv if file exists but its failing:
[ ! -f src/java/world.java ] || mkdir -p src/examples/ && mv src/java/world.java src/examples/world.java
Is there any option to check if path src
, src/java
and file exists?
Or just fail and keep returning zero
CodePudding user response:
Group your commands after the file check:
[ ! -f src/java/world.java ] || (mkdir -p src/examples/ && mv src/java/world.java src/examples/world.java)
Everything within the parenthesis will only be executed if src/java/world.java exists.
Example of this in action (note the srcX in the SOURCE parameter of mv:
$ [ ! -f src/java/world.java ] || mkdir -p src/examples/ ; mv srcX/java/world.java src/examples/world.java
mv: cannot stat 'srcX/java/world.java': No such file or directory
$ [ ! -f src/java/world.java ] || (mkdir -p src/examples/ ; mv srcX/java/world.java src/examples/world.java)
Since you're already checking for the full file path, then it doesn't really matter if src or src/java doesn't exist since world.java wouldn't exist in either case - unless you want to generate more appropriate errors.
CodePudding user response:
While AND and OR lists (list1 && list2
and list1 || list2
) are appealing to make short code, they should only be used for simple tasks based on single commands. Anything else inhibits readability and maintainability of your code. In the case of the OP, I would suggest to use a sime if
-statement and write everything as
if [ -f /path/to/file ]; then
mkdir -p -- /path/to/dir
mv -- /path/to/file /path/to/dir
fi
This code is now very readable and states, if file exists, then do some stuff.
Complex combinations of AND and OR lists mainly lead to unexpected behaviour because the implementation made assumptions. A simple example is cmd1 && cmd2 || cmd3
. Here cmd3
is executed when cmd1
OR cmd2
returns a non-zero return-status and not only when cmd1
returns false.