LFCA 14 ๐ง Creating Files and Directories โ touch, mkdir
Everything on a Linux filesystem starts as a file or a directory. Directories are the containers; files are the content. Two commands create them: mkdir makes directories, touch creates empty files (or updates timestamps). They’re the first step in almost every workflow โ you need somewhere to put files, and you need files to put content in. The LFCA exam expects you to know both commands, their flags, the parent-child relationship between them, and the permissions and defaults that apply when you create them.
Key point: mkdir creates directories. touch creates empty files and updates timestamps on existing ones. They’re built on the same foundation โ filesystem entries โ but serve different purposes. mkdir -p creates parent directories as needed; touch on an existing file updates its access and modification times. Together they give you the basic operation of turning “nothing” into “something” on disk.
What files and directories are
A file is a named sequence of bytes on disk โ text, binary, anything. A directory is a special file that holds a list of entries: the names of files and subdirectories it contains.
Files:
- Hold content โ text, images, executables, config
- Have a type (regular, directory, symlink, device, socket, pipe)
- Have permissions, owner, group, timestamps
- Can be empty (zero bytes)
Directories:
- Hold entries โ names and inode numbers
- Are themselves files (a special kind)
- Can be empty or nested
- Form the tree of the filesystem
The relationship:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Directory โ
โ โโโ file1.txt (regular file) โ
โ โโโ subdir/ (directory) โ
โ โ โโโ file2.txt (regular file) โ
โ โโโ link โ file1.txt (symlink) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
What you create with each command:
| Command | Creates |
|---|---|
mkdir NAME | A directory |
touch NAME | An empty file (or updates timestamps) |
Why they matter: Every project, script, or workflow starts with creating a place to work. mkdir myproject && cd myproject && touch README.md is the skeleton of almost anything. These are the first commands anyone runs after navigating.
Why “touch” is an odd name: The original Unix
touchwas designed to update a file’s modification time without changing content โ “touching” it as if you’d edited it. It also creates the file if it doesn’t exist. The name stuck, even though creating empty files is now its most common use.
mkdir โ create directories
mkdir creates one or more directories.
$ mkdir projects
$ ls
projects
Creates a directory called projects in the current directory.
Creating multiple directories:
$ mkdir docs images scripts
$ ls
docs images scripts
Each argument is a separate directory. They’re all created in the current directory.
Absolute path:
$ mkdir /tmp/work
Creates /tmp/work.
Relative path:
$ mkdir subdir
Creates subdir inside the current directory.
Default permissions: mkdir creates directories with permissions based on the umask.
$ umask
0022
$ mkdir test
$ ls -ld test
drwxr-xr-x 2 alice alice 4096 Sep 22 10:30 test
The default mode for mkdir is 777 (rwx for all), minus the umask. With umask 022, the result is 755 (drwxr-xr-x).
Why permissions depend on umask: The umask masks off bits that new files and directories shouldn’t have. 022 removes write permission for group and others. That’s the standard default โ the owner has full access, everyone else can read and traverse.
Failure cases:
$ mkdir existing
mkdir: cannot create directory 'existing': File exists
$ mkdir /root/forbidden
mkdir: cannot create directory '/root/forbidden': Permission denied
$ mkdir /nonexistent/subdir
mkdir: cannot create directory '/nonexistent/subdir': No such file or directory
The three common failures: the name exists, permission denied, or the parent doesn’t exist. The third is fixed by -p.
Why mkdir matters: Directories are the structure of a filesystem. Every project, every category, every hierarchical organization starts with mkdir. It’s the most basic structural operation.
Why
mkdircan’t overwrite: Creating a directory that already exists is an error โ silently succeeding could mask bugs. If you want it to succeed whether or not it exists, usemkdir -p. The default behavior is to fail loudly, which is the safer choice.
mkdir -p โ create parents
mkdir -p creates parent directories as needed and doesn’t fail if the directory exists.
$ mkdir -p projects/web/src
$ find projects
projects
projects/web
projects/web/src
-p creates every level of the path โ projects, projects/web, and projects/web/src โ even though only the last one was named.
Without -p:
$ mkdir projects/web/src
mkdir: cannot create directory 'projects/web/src': No such file or directory
The parent projects/web doesn’t exist, so the operation fails.
Idempotent:
$ mkdir -p existing
$ mkdir -p existing
$ echo $?
0
mkdir -p succeeds silently if the directory already exists. That makes it safe to include in scripts โ no need to check first.
What -p does in detail:
- Creates missing parent directories
- Succeeds if the target already exists
- Doesn’t fail if the target is a directory
Multiple paths with -p:
$ mkdir -p a/b/c d/e/f
$ find a d
a
a/b
a/b/c
d
d/e
d/e/f
Each path is created independently.
When to use -p: Almost always. When the parent might not exist, when the directory might already exist, when you’re scripting. -p makes mkdir forgiving, and forgiving is what you want in automation.
Other flags:
| Flag | Effect |
|---|---|
-p | Create parents, don’t fail if exists |
-m MODE | Set mode explicitly (not affected by umask) |
-v | Verbose โ print each directory created |
Setting mode:
$ mkdir -m 700 private
$ ls -ld private
drwx------ 2 alice alice 4096 Sep 22 10:30 private
-m 700 creates the directory with permissions 700 (rwx------), ignoring the umask.
Verbose:
$ mkdir -pv a/b/c
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
-v prints each created directory. Useful for scripts that log.
Why -p is idiomatic: It’s the safe default for scripts. mkdir -p /var/log/myapp works whether or not /var/log/myapp exists. Without -p, you’d have to check first. The flag removes that boilerplate.
Why
-pand not a separate command: The Unix philosophy favors flags over new commands.-pextendsmkdirwith “create parents” โ the same operation, just more forgiving. It’s the standard way to say “make this path exist, whatever it takes.”
touch โ create empty files
touch creates an empty file if it doesn’t exist, or updates its timestamps if it does.
$ touch notes.txt
$ ls -l notes.txt
-rw-r--r-- 1 alice alice 0 Sep 22 10:30 notes.txt
Creates a zero-byte file called notes.txt. The permissions come from the umask โ default 644 (rw-r--r--).
Creating multiple files:
$ touch a.txt b.txt c.txt
$ ls
a.txt b.txt c.txt
Each argument is a separate file.
Updating an existing file’s timestamps:
$ ls -l notes.txt
-rw-r--r-- 1 alice alice 0 Sep 22 10:30 notes.txt
$ touch notes.txt
$ ls -l notes.txt
-rw-r--r-- 1 alice alice 0 Sep 22 10:35 notes.txt
The modification time changes. The content is unchanged.
What touch updates:
- Access time (atime) โ when the file was last read
- Modification time (mtime) โ when the file was last modified
Both are set to the current time.
What touch does not do:
- Doesn’t write content
- Doesn’t change permissions
- Doesn’t follow symlinks unless told to (see below)
Permissions of new files: Like mkdir, touch respects the umask. The default mode for new files is 666 (rw-rw-rw-) minus the umask, giving 644 under umask 022.
Failure cases:
$ touch /root/forbidden
touch: cannot touch '/root/forbidden': Permission denied
$ touch /nonexistent/dir/file.txt
touch: cannot touch '/nonexistent/dir/file.txt': No such file or directory
Permission denied or missing parent directory.
Why touch matters: It’s the quickest way to create a file. Before writing to a file with an editor, you often need it to exist. touch creates it empty, ready to be edited. It’s also how you update timestamps without editing content โ useful for build systems that check mtime.
Why “create an empty file” is an accident of history:
touchwas designed for timestamps. Creating empty files was a side effect. But it turned out to be the most useful part โ the timestamp behavior is now a secondary feature. The command stuck because both purposes are valuable.
touch flags and timestamp control
touch has flags for updating specific timestamps and setting them explicitly.
-a โ access time only:
$ touch -a notes.txt
Updates only the access time, not the modification time.
-m โ modification time only:
$ touch -m notes.txt
Updates only the modification time, not the access time.
-c โ don’t create:
$ touch -c nonexistent.txt
$ ls nonexistent.txt
ls: cannot access 'nonexistent.txt': No such file or directory
-c (or --no-create) updates timestamps if the file exists but doesn’t create it if it doesn’t.
-t โ set a specific timestamp:
$ touch -t 202509221030 notes.txt
Sets the timestamp to September 22, 2025 at 10:30. Format is [[CC]YY]MMDDhhmm[.ss].
-d โ natural language timestamp:
$ touch -d "2025-09-22 10:30" notes.txt
$ touch -d "yesterday" notes.txt
$ touch -d "1 hour ago" notes.txt
-d accepts human-readable dates. Useful for testing or backdating.
-r โ reference another file:
$ touch -r source.txt target.txt
Sets target.txt‘s timestamps to match source.txt‘s.
-h โ affect symlinks, not their targets:
$ touch -h symlink
Updates the symlink itself, not the file it points to.
Common uses:
| Flag | Use |
|---|---|
-a | Update access time only |
-m | Update modification time only |
-c | Don’t create if missing |
-t TIMESTAMP | Set specific time |
-d DATE | Set from string |
-r FILE | Copy timestamps from file |
-h | Affect symlink, not target |
Why timestamps matter: Build systems, backup tools, and sync programs compare timestamps to decide what’s changed. Touching a file makes it “newer” โ that can trigger a rebuild, mark something as modified, or force a sync. The flags give you precise control over which timestamp and what value.
Why
-cis useful: In scripts, you might want to update a file’s timestamp if it exists but not create it if it doesn’t.-cgives that behavior. Without it,touchwould silently create the file, which might not be what the script intended.
Permissions on new files and directories
When you create a file or directory, the permissions come from the umask.
The umask:
$ umask
0022
The umask is an octal number. It masks off permission bits from the default mode.
How it works:
Default for directories: 777 (rwxrwxrwx)
Umask: 022
Result: 755 (rwxr-xr-x)
Default for files: 666 (rw-rw-rw-)
Umask: 022
Result: 644 (rw-r--r--)
The subtraction is bitwise:
777 โ 111 111 111
- 022 โ 000 010 010
= 755 โ 111 101 101
The bits set in the umask are removed from the default.
Common umasks:
| Umask | Directories | Files | Meaning |
|---|---|---|---|
| 022 | 755 | 644 | Standard (owner full, others read) |
| 002 | 775 | 664 | Group writable |
| 027 | 750 | 640 | Group read only, others nothing |
| 077 | 700 | 600 | Private (only owner) |
Setting the umask:
$ umask 077
$ touch private.txt
$ ls -l private.txt
-rw------- 1 alice alice 0 Sep 22 10:30 private.txt
The new file has 600 โ only the owner can read or write.
mkdir -m overrides the umask:
$ mkdir -m 700 private
$ ls -ld private
drwx------ 2 alice alice 4096 Sep 22 10:30 private
-m sets the mode explicitly, ignoring the umask.
touch has no -m: touch doesn’t set permissions directly โ that’s chmod. Create the file, then change its mode:
$ touch config.txt
$ chmod 600 config.txt
Why umask matters: Every new file and directory inherits the umask’s restrictions. It’s how you set default privacy for everything a user creates. Changing the umask changes the defaults for the session.
Why the umask is subtractive: You can’t add permissions with a umask โ only remove them. The default for files is
666(no execute, since new files aren’t executable). The default for directories is777(execute, because you need it to enter and use them). The umask then removes what you don’t want.
Combining mkdir and touch
The two commands work together constantly.
Create a project skeleton:
$ mkdir -p myproject/{src,docs,tests}
$ touch myproject/README.md
$ touch myproject/src/main.js
$ find myproject
myproject
myproject/README.md
myproject/docs
myproject/src
myproject/src/main.js
myproject/tests
mkdir -p with brace expansion creates the structure; touch fills in the files.
Brace expansion:
$ mkdir -p {a,b,c}
$ ls
a b c
{a,b,c} expands to a b c โ three arguments to mkdir.
Nested braces:
$ mkdir -p project/{src,test}/{js,css}
$ find project
project
project/src
project/src/css
project/src/js
project/test
project/test/css
project/test/js
The braces expand to project/src/js, project/src/css, project/test/js, project/test/css.
Creating files in a new directory:
$ mkdir data && cd data && touch record.txt
$ ls
record.txt
Chain the commands with &&. Each runs only if the previous succeeded.
Filling a directory:
$ mkdir logs
$ touch logs/{access,error,debug}.log
$ ls logs
access.log debug.log error.log
One mkdir, one touch, three files.
Why they’re almost always used together: Creating a directory without putting anything in it is uncommon. Creating a file without a place to put it is impossible. The two commands answer the two halves of “set up a place to work.”
Why brace expansion is a bash feature, not a
mkdirfeature: The shell expands{a,b,c}into three arguments before runningmkdir. The command seesmkdir a b c. That’s why brace expansion works with any command โ it’s shell-level syntax.
A full example
Setting up a project directory.
# ============================================
# PART 1: START FROM HOME
# ============================================
cd ~
pwd
# /home/alice
# ============================================
# PART 2: CREATE THE PROJECT ROOT
# ============================================
mkdir projects
ls
# Desktop Documents Downloads Music Pictures projects
# ============================================
# PART 3: NESTED DIRECTORIES
# ============================================
cd projects
mkdir -p web/src
# Creates web and web/src in one go
find .
# .
# ./web
# ./web/src
# ============================================
# PART 4: BRACE EXPANSION
# ============================================
mkdir -p myapp/{src,docs,tests}
find myapp
# myapp
# myapp/docs
# myapp/src
# myapp/tests
# ============================================
# PART 5: CREATE FILES
# ============================================
cd myapp
touch README.md
touch src/main.js
touch src/index.html
touch docs/guide.md
touch tests/main.test.js
find .
# .
# ./README.md
# ./docs
# ./docs/guide.md
# ./src
# ./src/index.html
# ./src/main.js
# ./tests
# ./tests/main.test.js
# ============================================
# PART 6: VERIFY
# ============================================
ls -la
# drwxr-xr-x 5 alice alice 4096 Sep 22 10:30 .
# drwxr-xr-x 3 alice alice 4096 Sep 22 10:30 ..
# -rw-r--r-- 1 alice alice 0 Sep 22 10:30 README.md
# drwxr-xr-x 2 alice alice 4096 Sep 22 10:30 docs
# drwxr-xr-x 2 alice alice 4096 Sep 22 10:30 src
# drwxr-xr-x 2 alice alice 4096 Sep 22 10:30 tests
ls -la src
# -rw-r--r-- 1 alice alice 0 Sep 22 10:30 index.html
# -rw-r--r-- 1 alice alice 0 Sep 22 10:30 main.js
# ============================================
# PART 7: IDEMPOTENT
# ============================================
mkdir -p src
# No error, already exists
mkdir -p another/missing/dir
# Creates all three levels
# ============================================
# PART 8: TOUCH ON EXISTING
# ============================================
ls -l README.md
# -rw-r--r-- 1 alice alice 0 Sep 22 10:30 README.md
sleep 2
touch README.md
ls -l README.md
# -rw-r--r-- 1 alice alice 0 Sep 22 10:32 README.md
# (mtime updated, content unchanged)
# ============================================
# PART 9: CREATE MULTIPLE FILES
# ============================================
touch notes.txt ideas.txt tasks.txt
ls
# README.md docs ideas.txt notes.txt src tasks.txt tests
touch logs/{access,error}.log
mkdir logs
# Order matters โ create the directory first
touch logs/{access,error}.log
ls logs
# access.log error.log
# ============================================
# PART 10: EXPLICIT MODE
# ============================================
mkdir -m 700 private
ls -ld private
# drwx------ 2 alice alice 4096 Sep 22 10:30 private
umask
# 0022
umask 077
touch secret.txt
ls -l secret.txt
# -rw------- 1 alice alice 0 Sep 22 10:30 secret.txt
umask 022 # restore
Each part demonstrates a different aspect of creating files and directories.
Why this session: It’s the workflow of setting up a project โ create the structure, fill it with files, verify, use brace expansion, handle permissions. Once these are muscle memory, project setup takes seconds.
Complete Example Session
# ============================================
# PART 1: CREATE A SINGLE DIRECTORY
# ============================================
mkdir testdir
ls -ld testdir
# [ drwxr-xr-x 2 alice alice 4096 Sep 22 10:30 testdir ]
# ============================================
# PART 2: MULTIPLE DIRECTORIES
# ============================================
mkdir dir1 dir2 dir3
ls
# [ dir1 dir2 dir3 testdir ]
# ============================================
# PART 3: PARENTS WITH -p
# ============================================
mkdir -p a/b/c/d
find a -type d
# [ a ]
# [ a/b ]
# [ a/b/c ]
# [ a/b/c/d ]
# ============================================
# PART 4: IDEMPOTENT
# ============================================
mkdir -p a/b/c/d
echo $?
# [ 0 ]
mkdir a/b/c/d
# [ mkdir: cannot create directory 'a/b/c/d': File exists ]
echo $?
# [ 1 ]
# ============================================
# PART 5: EXPLICIT MODE
# ============================================
mkdir -m 755 public
mkdir -m 700 private
mkdir -m 750 shared
ls -ld public private shared
# [ drwxr-xr-x 2 alice alice 4096 ... public ]
# [ drwx------ 2 alice alice 4096 ... private ]
# [ drwxr-x--- 2 alice alice 4096 ... shared ]
# ============================================
# PART 6: VERBOSE
# ============================================
mkdir -pv x/y/z
# [ mkdir: created directory 'x' ]
# [ mkdir: created directory 'x/y' ]
# [ mkdir: created directory 'x/y/z' ]
# ============================================
# PART 7: BRACE EXPANSION
# ============================================
mkdir -p project/{src,test}/{js,css}
find project
# [ project ]
# [ project/src ]
# [ project/src/css ]
# [ project/src/js ]
# [ project/test ]
# [ project/test/css ]
# [ project/test/js ]
# ============================================
# PART 8: TOUCH A SINGLE FILE
# ============================================
touch file1.txt
ls -l file1.txt
# [ -rw-r--r-- 1 alice alice 0 Sep 22 10:30 file1.txt ]
# ============================================
# PART 9: MULTIPLE FILES
# ============================================
touch alpha.txt beta.txt gamma.txt
ls *.txt
# [ alpha.txt beta.txt file1.txt gamma.txt ]
# ============================================
# PART 10: BRACE EXPANSION WITH FILES
# ============================================
touch report.{txt,html,pdf}
ls report.*
# [ report.html report.pdf report.txt ]
# ============================================
# PART 11: UPDATE TIMESTAMP
# ============================================
stat -c '%y %n' file1.txt
# [ 2025-09-22 10:30:00 file1.txt ]
sleep 2
touch file1.txt
stat -c '%y %n' file1.txt
# [ 2025-09-22 10:30:02 file1.txt ]
# ============================================
# PART 12: SET SPECIFIC TIMESTAMP
# ============================================
touch -t 202401010000 file1.txt
stat -c '%y %n' file1.txt
# [ 2024-01-01 00:00:00 file1.txt ]
touch -d "yesterday" file1.txt
stat -c '%y %n' file1.txt
# [ 2025-09-21 ... file1.txt ]
# ============================================
# PART 13: DON'T CREATE
# ============================================
touch -c missing.txt
ls missing.txt
# [ ls: cannot access 'missing.txt': No such file or directory ]
# ============================================
# PART 14: DON'T FOLLOW SYMLINKS
# ============================================
touch original.txt
ln -s original.txt link.txt
touch -h link.txt
# (updates the symlink, not original.txt)
# ============================================
# PART 15: UMASK
# ============================================
umask
# [ 0022 ]
touch default.txt
ls -l default.txt
# [ -rw-r--r-- ... default.txt ]
umask 077
touch private.txt
ls -l private.txt
# [ -rw------- ... private.txt ]
umask 022
# ============================================
# PART 16: FULL PROJECT
# ============================================
mkdir -p myweb/{public,src,config}
touch myweb/README.md
touch myweb/config/app.json
touch myweb/src/index.js
touch myweb/public/index.html
find myweb -type f
# [ myweb/README.md ]
# [ myweb/config/app.json ]
# [ myweb/public/index.html ]
# [ myweb/src/index.js ]
find myweb -type d
# [ myweb ]
# [ myweb/config ]
# [ myweb/public ]
# [ myweb/src ]
Every part exercises a mkdir or touch feature. Together they cover creation, structure, timestamps, and permissions.
Quick Reference
mkdir Flags
| Flag | Effect |
|---|---|
-p | Create parents, don’t fail if exists |
-m MODE | Set permissions explicitly |
-v | Verbose output |
--mode=MODE | Same as -m |
--parents | Same as -p |
touch Flags
| Flag | Effect |
|---|---|
-a | Update access time only |
-m | Update modification time only |
-c | Don’t create if missing |
-t STAMP | Set specific timestamp |
-d STRING | Natural language timestamp |
-r FILE | Copy timestamps from file |
-h | Affect symlink, not target |
Default Permissions
| Type | Default Mode | With umask 022 |
|---|---|---|
| Directory | 777 | 755 |
| File | 666 | 644 |
Common umasks
| Umask | Directories | Files |
|---|---|---|
| 022 | 755 | 644 |
| 002 | 775 | 664 |
| 027 | 750 | 640 |
| 077 | 700 | 600 |
Brace Expansion
| Form | Expands to |
|---|---|
{a,b,c} | a b c |
{1..5} | 1 2 3 4 5 |
{a..e} | a b c d e |
pre{a,b}post | preapost prebpost |
{a,b}{1,2} | a1 a2 b1 b2 |
Common Patterns
| Pattern | Command |
|---|---|
| Basic dir | mkdir NAME |
| Nested dirs | mkdir -p a/b/c |
| Multiple dirs | mkdir a b c |
| Brace expansion | mkdir -p {a,b,c} |
| Empty file | touch NAME |
| Multiple files | touch a.txt b.txt |
| Refresh mtime | touch EXISTING |
| Set timestamp | touch -t 202509221030 FILE |
| Private dir | mkdir -m 700 private |
Timestamp Format for -t
[[CC]YY]MMDDhhmm[.ss]
| Component | Meaning |
|---|---|
| CC | Century (optional) |
| YY | Year (2-digit) |
| MM | Month (01-12) |
| DD | Day (01-31) |
| hh | Hour (00-23) |
| mm | Minute (00-59) |
| .ss | Seconds (optional) |
Example: 202509221030 = 2025-09-22 10:30
touch -d Examples
| String | Meaning |
|---|---|
"2025-09-22" | Specific date |
"2025-09-22 10:30" | Date and time |
"yesterday" | One day ago |
"tomorrow" | One day ahead |
"1 hour ago" | One hour earlier |
"2 weeks ago" | Two weeks earlier |
What touch Updates
| Option | atime | mtime |
|---|---|---|
touch FILE | โ | โ |
touch -a FILE | โ | โ |
touch -m FILE | โ | โ |
File Type Creation
| Type | Command |
|---|---|
| Directory | mkdir |
| Empty file | touch |
| Symlink | ln -s target link |
| Hard link | ln target link |
| FIFO | mkfifo name |
| Device | mknod (root) |
Default Modes
| Command | Base mode | umask applies |
|---|---|---|
mkdir | 777 | โ |
touch | 666 | โ |
mkdir -m | given | โ |
Failure Cases
| Error | Cause | Fix |
|---|---|---|
File exists | Directory already there | Use -p or check |
No such file or directory | Parent missing | Use -p |
Permission denied | No write in parent | Check perms |
Read-only file system | FS is read-only | Remount or use writable |
Verifying Creation
| Command | Shows |
|---|---|
ls -ld DIR | Directory details |
ls -l FILE | File details |
find . -type d | All subdirs |
find . -type f | All files |
stat FILE | Full metadata |
tree | Tree view (if installed) |
Best Practices
โ Do This:
# Use -p almost always
mkdir -p /path/to/nested/dir # โ
# Use brace expansion for parallel dirs
mkdir -p project/{src,docs,tests} # โ
# Set explicit modes for sensitive dirs
mkdir -m 700 ~/.private # โ
# Verify after creation
mkdir data && ls -ld data # โ
# Chain with && for dependencies
mkdir logs && touch logs/app.log # โ
# Use verbose in scripts
mkdir -pv /var/log/myapp # โ
# Touch to update without editing
touch config.ini # โ
# Use -c when you don't want to create
touch -c logfile # โ
# Set specific timestamps for testing
touch -t 202401010000 file.txt # โ
# Combine mkdir and touch
mkdir -p app/{src,tests} && touch app/README.md # โ
โ Don’t Do This:
# Don't create without checking if you care
mkdir existing # fails if exists # โ ๏ธ
# Don't forget -p for nested paths
mkdir a/b/c # fails if a/b doesn't exist # โ
# Don't use touch for content
touch file.txt
echo "content" > file.txt # โ
# โ
# Don't create world-writable dirs
mkdir -m 777 shared # โ ๏ธ everyone can write # โ ๏ธ
# Don't touch a file you want unchanged
touch important.log # โ ๏ธ updates mtime # โ ๏ธ
# Don't create files in /tmp for persistence
touch /tmp/data # cleared on reboot # โ
# Don't ignore permission errors
mkdir /root/x # fails, check why # โ ๏ธ
# Don't forget brace expansion is shell-level
# It doesn't work in quotes # โ ๏ธ
# Don't create in the wrong directory
mkdir project # where are you? # โ ๏ธ
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
No -p | Nested path fails | Use -p |
| Existing directory | File exists | Use -p |
| Wrong permissions | Too open or closed | Use -m or umask |
| Missing parent | No such file | mkdir -p first |
Forgot to cd | Created in wrong place | Check pwd |
touch overwrites | Actually doesn’t | It only updates mtime |
| Umask surprise | Files more open | Check umask |
| Brace not expanding | Quoted braces | Unquote them |
| Empty file expected | Non-empty | touch creates 0-byte |
| Timestamp format wrong | -t rejects | Use [[CC]YY]MMDDhhmm |
Real-World Examples
1. Create one directory
mkdir myproject
2. Create nested path
mkdir -p projects/web/src
3. Multiple directories
mkdir html css js images
4. Brace expansion
mkdir -p app/{src,test,docs}
5. Private directory
mkdir -m 700 ~/.ssh
6. Verbose creation
mkdir -pv /var/log/myapp
7. Create one file
touch readme.txt
8. Multiple files
touch a.txt b.txt c.txt
9. Brace expansion for files
touch log.{txt,html,json}
10. Update mtime
touch existing.txt
11. Set old timestamp
touch -t 202401010000 report.txt
12. Relative timestamp
touch -d "1 week ago" archive.txt
13. Copy timestamps
touch -r reference.txt new.txt
14. Don’t create if missing
touch -c optional.txt
15. Update only atime
touch -a notes.txt
16. Create project skeleton
mkdir -p myapp/{src,tests,docs}
touch myapp/README.md
touch myapp/src/index.js
17. Log directory setup
touch /var/log/myapp/app.log
18. Test directory
mkdir -p /tmp/test/{input,output,logs}
19. Backup structure
mkdir -p backups/{daily,weekly,monthly}
20. Empty file for placeholder
touch .gitkeep
Visual: mkdir and touch
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ mkdir projects โ
โ โ
โ Current directory: โ
โ โโโ projects/ โ new โ
โ โ โ
โ โโโ ... โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ touch projects/README.md โ
โ โ
โ projects/: โ
โ โโโ README.md โ new (0 bytes) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: mkdir -p
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ mkdir -p a/b/c/d โ
โ โ
โ a/ โ
โ โโโ b/ โ
โ โโโ c/ โ
โ โโโ d/ โ
โ โ
โ All four created in one command โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ mkdir a/b/c/d โ
โ โ
โ mkdir: cannot create directory 'a/b/c/d': โ
โ No such file or directory โ
โ โ
โ Only works if a/b/c already exists โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Default Permissions
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Directories โ
โ โ
โ Base mode: 777 rwxrwxrwx โ
โ umask: 022 ----w--w- โ
โ Result: 755 rwxr-xr-x โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Files โ
โ โ
โ Base mode: 666 rw-rw-rw- โ
โ umask: 022 ----w--w- โ
โ Result: 644 rw-r--r-- โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Why different base modes? โ
โ โ
โ Directories need x to enter โ
โ Files don't need x (unless executable) โ
โ โ
โ New files: no execute by default โ
โ New directories: execute for all by default โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Brace Expansion
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ mkdir -p project/{src,test}/{js,css} โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ shell expands
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ mkdir -p project/src/js \ โ
โ project/src/css \ โ
โ project/test/js \ โ
โ project/test/css โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Result: โ
โ โ
โ project/ โ
โ โโโ src/ โ
โ โ โโโ js/ โ
โ โ โโโ css/ โ
โ โโโ test/ โ
โ โโโ js/ โ
โ โโโ css/ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: touch Timestamps
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Before touch โ
โ โ
โ File: notes.txt โ
โ atime: 10:00 โ
โ mtime: 10:00 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ (wait 5 minutes)
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ touch notes.txt โ
โ โ
โ atime: 10:05 โ updated โ
โ mtime: 10:05 โ updated โ
โ โ
โ Content: unchanged โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: touch -a vs -m
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ touch -a FILE โ
โ โ
โ atime: updated โ
โ
โ mtime: unchanged โ
โ โ
โ (access time only) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ touch -m FILE โ
โ โ
โ atime: unchanged โ
โ mtime: updated โ
โ
โ โ
โ (modification time only) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ touch FILE โ
โ โ
โ atime: updated โ
โ
โ mtime: updated โ
โ
โ โ
โ (both) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Building a Project
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Step 1: Create structure โ
โ โ
โ mkdir -p myapp/{src,test,docs} โ
โ โ
โ myapp/ โ
โ โโโ src/ โ
โ โโโ test/ โ
โ โโโ docs/ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Step 2: Add files โ
โ โ
โ touch myapp/README.md โ
โ touch myapp/src/index.js โ
โ touch myapp/test/index.test.js โ
โ touch myapp/docs/guide.md โ
โ โ
โ myapp/ โ
โ โโโ README.md โ
โ โโโ src/ โ
โ โ โโโ index.js โ
โ โโโ test/ โ
โ โ โโโ index.test.js โ
โ โโโ docs/ โ
โ โโโ guide.md โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: umask Effect
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ umask 022 โ
โ โ
โ mkdir dir โ drwxr-xr-x (755) โ
โ touch file โ -rw-r--r-- (644) โ
โ โ
โ Owner: full โ
โ Group: read โ
โ Others: read โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ umask 077 โ
โ โ
โ mkdir dir โ drwx------ (700) โ
โ touch file โ -rw------- (600) โ
โ โ
โ Owner: full โ
โ Group: nothing โ
โ Others: nothing โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: File Types Created
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ mkdir NAME โ directory โ
โ touch NAME โ empty regular file โ
โ ln -s T L โ symbolic link โ
โ ln T L โ hard link โ
โ mkfifo NAME โ named pipe (FIFO) โ
โ mknod ... โ device (root only) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Common Workflow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Create project structure: โ
โ โ
โ 1. mkdir -p app/{src,tests,docs} โ
โ โ โ
โ โผ โ
โ 2. cd app โ
โ โ โ
โ โผ โ
โ 3. touch README.md โ
โ โ โ
โ โผ โ
โ 4. touch src/main.js โ
โ โ โ
โ โผ โ
โ 5. Verify with ls -R โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Decision Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need a directory? โ
โ โ โ
โ โโโ mkdir [ -p ] NAME โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need an empty file? โ
โ โ โ
โ โโโ touch NAME โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Path has missing parents? โ
โ โ โ
โ โโโ Use -p โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need specific permissions? โ
โ โ โ
โ โโโ mkdir -m MODE or set umask โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Creating multiple at once? โ
โ โ โ
โ โโโ Brace expansion { a,b,c } โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Only want to update timestamp? โ
โ โ โ
โ โโโ touch EXISTING โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Command | Purpose |
|---|---|
mkdir NAME | Create a directory |
mkdir -p PATH | Create parents if needed |
mkdir -m MODE | Set permissions explicitly |
touch NAME | Create empty file or update timestamps |
touch -a | Update access time only |
touch -m | Update modification time only |
touch -c | Don’t create if missing |
touch -t | Set specific timestamp |
Key takeaways:
mkdircreates directories;touchcreates empty files or updates timestampsmkdir -pcreates missing parent directories and doesn’t fail if the target exists โ use it almost alwaysmkdir -msets permissions explicitly, ignoring the umasktouchon an existing file updates its timestamps without changing contenttouch -aupdates only access time;-monly modification timetouch -cupdates timestamps but doesn’t create the file if it’s missingtouch -tsets a specific timestamp;-daccepts natural language dates- Default permissions come from the umask โ 755 for directories, 644 for files with
umask 022 - Brace expansion โ
{a,b,c}โ creates multiple entries in one command; the shell expands it - Common workflow โ
mkdir -pthe structure, thentouchthe files - Verify with
ls -l,find, orstat
Remember: Creating files and directories is the most basic operation on a Linux filesystem. mkdir builds the structure; touch fills it with empty files. Use -p for safety, -m for permissions, and brace expansion for efficiency. Check where you are before creating โ the directory you’re in is where the new entry will land. Once you can create files and directories confidently, the rest of the filesystem โ copying, moving, editing, removing โ builds on this foundation.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!