Single command to create a file and set its permission
ShellUnixFile PermissionsKshShell Problem Overview
I am using the following 2 commands to create a 0B file and set its extn to 644
touch filename.ext
chmod 777 filename.txt
My question is that whether there is any single command in unix (korn shell) that will do the two things together that is to say create a 0B fil with desired permission?
Shell Solutions
Solution 1 - Shell
install -m 777 /dev/null filename.txt
Solution 2 - Shell
For bash
, simply use chmod
with file redirection and history expansion:
chmod 777 filename.txt>>!#:2
For ksh
and zsh
you have to drop the history expansion (as shown above, there may be other ways) and use:
chmod 644 filename>>filename
For scripts of any shell you don't have (and really don't need) history expansion so use the above there as well.
Solution 3 - Shell
First of all, you should NEVER be setting anything to 777
permissions. This is a huge security problem and there just isn't any need for it. For the purposes of this question I will assume you want to create a file with more secure permissions than the defaults, say 600
.
There is not a one stop way to safely create AND change the permissions of a file using most bash tools. Even the tricky redirection trick in Paul's answer actually momentarily creates a file with default permissions before resetting them. All new files get created with whatever the system umask value is set too unless the creating program sends very specific requests to the operating system at the time of node creation. A mask of 133
is common, meaning your files get created with 644
permissions out of the box.
Besides using the chmod
command to set the file permissions after you create a file, you can also tell the system what defaults you want using the umask
command.
$ umask 077
$ touch test_file
$ ls -l test_file
-rw------- 1 user group 0 Jan 24 22:43 test_file
You will note the file has been created with 600
permissions.
This will stay in effect for all commands run in a shell until you either close that shell or manually set another value. If you would like to use this construct to run a single command (or even a small set of them) it can be useful to isolate the commands in a subshell
$ (umask 077 ; touch test_file)
Note that anything else you put inside the parens will use that umask but as soon as you close it, you are back in your previous environment.
Solution 4 - Shell
If you want to create the file not just empty but with content and mode at the same time you can use process substitution with install
in bash:
install -m 755 <(echo commands go here) newscript
<()
places the output into a temporary file (Process-Substitution)
Solution 5 - Shell
You can create your own command:
create () {
touch "$1"
chmod "$2" "$1"
}
create filename.ext 644
Solution 6 - Shell
The only reason your files are not created with 666 permissions right off of the bat is the umask
. So if you disable the umask
:
umask 0
then when you touch
the file it will end up with permissions 666 automatically. It would not be a good idea to make text files executable usually. Directories would end up with 777 permission with umask
disabled.
chicks@freecandy /tmp $ umask
0022
chicks@freecandy /tmp $ touch x
chicks@freecandy /tmp $ mkdir xx
chicks@freecandy /tmp $ umask 0
chicks@freecandy /tmp $ touch y
chicks@freecandy /tmp $ mkdir yy
chicks@freecandy /tmp $ ls -ld x xx y yy
-rw-r--r-- 1 chicks chicks 484 Jan 24 14:37 x
drwxr-xr-x 2 chicks chicks 4096 Jan 24 14:37 xx
-rw-rw-rw- 1 chicks chicks 0 Jan 24 14:37 y
drwxrwxrwx 2 chicks chicks 4096 Jan 24 14:37 yy
Solution 7 - Shell
touch filename.ext && chmod 777 $_
$_ is the most recent parameter
but as others have said 777 isn't a good idea
Solution 8 - Shell
Applying this to Docker
Because of Docker and Alpine, I imagine there are a lot of people interested in creating executable one-liners without the help of bash-isms. It's pretty simple with install
$ docker build -t temp - <<EOF
FROM alpine
RUN echo "date" | install -m 775 /dev/stdin /bin/now
CMD /bin/now
EOF
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM alpine
---> d6e46aa2470d
Step 2/3 : RUN echo "date" | install -m 775 /dev/stdin /bin/now
---> Running in 95919b575638
Removing intermediate container 95919b575638
---> cd1fafd96ef3
Step 3/3 : CMD /bin/now
---> Running in 03b5c3ac7265
Removing intermediate container 03b5c3ac7265
---> 8f30b527dd29
Successfully built 8f30b527dd29
Successfully tagged temp:latest
$ docker run --rm temp
Thu Nov 12 07:44:24 UTC 2020
$ docker run --rm temp ls -la /bin/now
-rwxrwxr-x 1 root root 5 Nov 12 07:44 /bin/now
$ docker rmi temp
Untagged: temp:latest
Deleted: sha256:8f30b527dd29203b67c86290b34b0a29d3c98a48134609d0b1e2b89087a7d6e7
Deleted: sha256:cd1fafd96ef3084226c5f98f472e3e08bc9a9f0448cc3e68b6f1c192d12d778a
Deleted: sha256:e58c75acbf953a64d35089cf50e1c5b762601e1cb9d9d1d668e135f23ce1fe86
Update
A commenter said:
> I don't get what this has to do with the question.
- The OP's subject for this Q was "Single command to create a file and set its permission"
- The OP included "single command in unix (korn shell) that will do the two things together"
The subject causes this Q to come up for Docker users' Google searches. The OP specified "korn shell" which implies avoiding bash specific features. Because Alpine and many other minimal Linux bases used in containers does not include bash, the top ranked answer is not going to work for them. My answer does work for them and the OP's korn shell. Using Docker to demonstrate a solution means that anyone using Linux, macOS, Windows, or WSL2 in Windows can easily recreate the demo on their machine by reading the transcript from my machine.