Developer Utilities

Unix Permission Calculator

Convert between chmod octal modes, rwx symbols, and special permission bits.

Unix file permissions
chmod · rwx · setuid · setgid · sticky
ScopeReadWriteExecuteDigit
Owner7
Group5
Others5
Permission result
755Octal
-rwxr-xr-xSymbolic
Command
chmod 755 <path>

Unix Permission Calculation

Convert between chmod octal modes and rwx symbolic notation, including setuid, setgid, and sticky special bits.

Reading Modes

  • Read, write, and execute have values 4, 2, and 1
  • The three groups represent owner, group, and others
  • The generated command uses a placeholder path that must be reviewed before execution

Converts a chmod mode between its octal digits and the ten-character rwx string printed by ls -l, including the setuid, setgid and sticky bits that live in a fourth digit. Useful for decoding an unfamiliar mode in a file listing, auditing a deployed script, or deciding which digit to change.

Each digit is a 3-bit field, not a number

An octal mode is not one value but three independent base-8 digits, read left to right as owner, group and others. Inside a digit the bit values are read=4, write=2, execute=1, and those three sum to a unique total between 0 and 7, which is the only reason the shorthand is unambiguous: rw- is 4+2=6, r-x is 4+1=5, --- is 0. The calculator resolves a digit into flags with a bitwise AND against 4, 2 and 1 rather than parsing it as a decimal number, and the table prints the resulting digit per scope, so toggling one checkbox rewrites one digit and leaves the other two untouched.

Why the special bits print as s, S, t or T

A fourth digit is prepended whenever a special bit is set: 4 for setuid, 2 for setgid, 1 for sticky, so 4755 and 1777 are four digits while 755 is three. The symbolic string overlays the flag on the execute slot of the scope it governs — setuid on owner x, setgid on group x, sticky on others x — and keeps case meaningful. Lowercase s or t means flag plus execute are both set; uppercase S or T means the flag is set while execute is cleared. The uppercase forms are not cosmetic: 4644 carries setuid with no execute bit, a state that can exist on disk but cannot be invoked normally, and exactly the thing to chase during an audit.

Where the mode string stops carrying information

The ten characters follow ls -l layout, but the leading position is fixed at - because a permission mode contains no file type; that byte comes from higher st_mode bits, such as 0100000 for a regular file and 0040000 for a directory. The last nine characters also say nothing about whether access will be granted. Effective access is the intersection of the mode with any POSIX ACL, with mount flags such as noexec, and on hardened hosts with SELinux or AppArmor labels; root bypasses read and write checks through CAP_DAC_OVERRIDE. Execute on a directory means traverse, so 644 on a directory renders it unusable however favourable the digits look.

Worked example

Reading a setgid shared-directory mode

Input
2775
Output
2775 | -rwxrwsr-x | chmod 2775 <path>

The leading 2 sets setgid and 775 gives the group rwx; because the group execute bit is already on, setgid renders as lowercase s instead of S. The mode is echoed with four digits because the special digit is non-zero — enter 0755 and it comes back as 755 — and the first character stays - since a mode has no type bit.

Limits and pitfalls

  • Input must be exactly 3 or 4 digits in 0–7; chmod itself also accepts a 2-digit mode such as 64, and symbolic forms like u+x are not handled here.
  • The result is a mode, not an access verdict: umask, ACL entries, noexec mounts and SELinux labels are outside the calculation.
  • A special digit of 0 is dropped from the output, so 0755 in becomes 755 out; extended st_mode values such as 100644 are rejected because the field holds four characters.
  • The first character of the symbolic string is always -, so directories (d) and symlinks (l) are indistinguishable from regular files.
  • The command contains a literal placeholder <path> that must be replaced; run against a directory without -R, it changes only that entry, not its contents.

Related tools

When it goes wrong

I pasted the mode from stat — 100644 — and got a mode with the sticky bit set instead of an error.

CauseThe field carries maxlength="4", so the browser cuts the paste down to 1006 before Vue ever sees it, and 1006 satisfies /^(?:[0-7]{3}|[0-7]{4})$/: the leading 1 is read as sticky and the remaining 006 as owner 0, group 0, others rw-. The printed string is -------rwT, and no warning appears at any point.

FixStrip the type bits before pasting, because a mode is only the last three or four octal digits: 100644 is 644, 040755 is 755. Compare the printed octal with the source afterwards — a truncated paste fails silently, an illegal character does not.

I unticked group write, clicked Apply, and the table jumped straight back to the previous mode.

CauseApply parses the text field, not the checkboxes. applyOctal() reads octalInput and writes the result back into that same field only after a successful parse, so a checkbox change never propagates into it. The result card is reactive and the field is not, which makes Apply re-apply a stale string.

FixTick the boxes and read the octal and symbolic values from the result card, copying the command from there. Reach for Apply only when travelling the other way, from a typed mode into individual bits.

The owner execute slot shows s, the file belongs to root, and it still runs with my own user id.

CauseThe page prints a mode, while the kernel layers on rules a mode cannot express. Linux ignores setuid on #! scripts and runs the interpreter with the caller’s credentials, and a filesystem mounted nosuid strips the bit even from a real ELF binary.

FixRun findmnt -no OPTIONS --target /path/to/file to rule out nosuid, then confirm the owner with ls -l. If the target is a script, replace it with a compiled wrapper or one narrowly scoped sudo rule rather than editing more digits.

I set 1644 on a file in a shared folder so that others could not delete it, and they still can.

CauseSticky constrains directory entries, not the file: the kernel honours it only when the containing directory carries +t, and on Linux the historical "keep the text image on swap" meaning of a sticky regular file has been gone for years. This page still prints a t for 1644 because a mode contains no file-type bit that could tell it otherwise.

FixMove the bit to the directory (chmod 1777 shared/), or withdraw write permission on that directory from the group — unlinking an entry requires write on the containing directory, never anything on the file itself.

Modes copied out of our Python settings, like 0o755, are rejected even though the error message offers 755 as a valid example.

CauseValidation is a single anchored pattern over the octal digit class, so the 0o prefix has nowhere to go — and because the field stops at four characters, 0o755 reaches the validator as 0o75, failing both the length and the digit class at once.

FixType plain octal digits: 755, or 0644 for the four-digit shape, which is accepted and echoed back as 644. Keep the prefix in the source file and translate it on the way in.

Every string this calculator can print, one octal digit at a time

Value in the fieldHow that position printsWhat the bits actually grant
0---Nothing: the scope cannot read, write or run the file. A directory at --- cannot be listed or entered by its own owner either — chmod still works only because that call checks ownership, not mode.
1--xExecute alone: a binary you may run but not copy. On a directory this is the bare traverse bit, so an exact path resolves and ls is refused.
2-w-Write alone: echo x >> f and truncation succeed while cat f fails. Applied to a directory, a name you already know can be created or unlinked, but listing and traversal both fail.
3-wxThe drop-box digit: on a directory, entries can be created, removed and reached by exact name, yet the directory itself cannot be enumerated.
4r--Read only. As a directory mode it returns names and nothing else — every entry fails to stat, so ls -l shows question marks where sizes and timestamps belong.
5r-xRead and execute, no write. The normal directory mode, and the normal mode for scripts and binaries that everyone should be able to run.
6rw-The normal file mode. Put it on a directory and you get the classic lockout: names can still be listed, but nothing inside can be opened or traversed because execute is missing.
7rwxAll three. Correct for directories that genuinely need to be written; on a file in a shared tree it hands anyone the right to rewrite and run it.
4000owner execute slot becomes s, or S when execute is clearedsetuid. Linux ignores it on #! scripts and on nosuid mounts, so a perfectly typed 4755 can still execute as the caller.
2000group execute slot becomes s or Ssetgid. On a directory, new entries inherit the group of that directory and new subdirectories keep the bit themselves.
1000others execute slot becomes t or Tsticky. Inside that directory, unlinking is limited to the file owner, the directory owner and root — /tmp at 1777 is the canonical case.
60006755 prints -rwsr-sr-xsetuid plus setgid, for the rare privileged tool that also needs group inheritance. If one execute bit is off, the same string carries a lowercase s and an uppercase S side by side.
50005755 prints -rwsr-xr-tsetuid plus sticky: a shared drop directory that also holds one privileged helper.
30003755 prints -rwxr-sr-tsetgid plus sticky: a group-shared directory where only the file owner may delete their own entries.
70007777 prints -rwsrwsrwtAll three flags. Each slot prints the lowercase letter only where execute is already set, so 7766 yields -rwsrwSrwT-style strings that rarely mean what was intended.

The leading digit follows the same 4 + 2 + 1 addition as the others, so its only legal values are 1 to 7, and the three checkboxes above the table are what set it — the field merely carries it in and out.

Frequently Asked Questions

What do 755 and 644 actually mean?
Each digit sums rwx values (r=4, w=2, x=1): 755 = owner rwx, group and others r-x — for directories and executable scripts; 644 = owner rw-, group and others r-- — for regular files. Treat 777 as an alarm bell: world-writable is how incidents happen.
What is the leading fourth digit in 4755?
Special bits: 4=setuid (runs as the file’s owner), 2=setgid (inherits the group), 1=sticky (in a directory, only the owner can delete their own files — /tmp is 1777). setuid is common on privileged system tools and a prime audit target.
What permissions should a web server deployment use?
Rules of thumb: directories 755, static files 644, config files with secrets 600, upload directories writable by the runtime user but not executable. Principle: least privilege — the process reads what it needs, writes only where it must.

Content reviewed: