I can write:
X=""
if [ -f foo.txt ]; then
X=$(<foo.txt)
fi
but this is 4 lines. Is there a more compact way to express this logic?
If you do just X=$(< foo.txt), X will be empty if the file doesn't exist, but you'll get an error message:
$ X=$(< foo.txt)
-bash: foo.txt: No such file or directory
If you want to suppress that (but also any other error message), you can redirect stderr to /dev/null:
{ X=$(< too.txt); } 2> /dev/null
X is in fact empty afterwards:
$ declare -p X
declare -- X="
x=$(cat file 2>&-).