Developer

CHMOD Calculator

Set Unix file permissions visually. Toggle checkboxes or type a numeric code — everything syncs live. Get the ready-to-use chmod command.

Owner
Group
Others
Entity Read (r) = 4 Write (w) = 2 Execute (x) = 1
u Owner
g Group
o Others
Numeric
755
Symbolic
rwxr-xr-x
Octal
0755
chmod command
chmod 755 filename
recursive (directories)
chmod -R 755 directory/
Owner
7
Read + Write + Execute
Group
5
Read + Execute
Others
5
Read + Execute
644
rw-r--r--
Files
755
rwxr-xr-x
Directories
777
rwxrwxrwx
Full access
600
rw-------
Private
400
r--------
Read-only
700
rwx------
Owner only
664
rw-rw-r--
Group write
775
rwxrwxr-x
Group dir
Developer Reference

Core Algorithm & Standalone Script

Standalone, zero-dependency JavaScript implementation powering this tool. Free to inspect, copy, and build upon.

function clamp(v) { return Math.max(0, Math.min(7, isNaN(v) ? 0 : v)); }

  function bitDesc(n) {
    const p = [];
    if (n & 4) p.push('Read');
    if (n & 2) p.push('Write');
    if (n & 1) p.push('Execute');
    return p.length ? p.join(' + ') : 'No permissions';
  }

  function toBits(n) {
    return (n&4?'r':'-') + (n&2?'w':'-') + (n&1?'x':'-');
  }

  function updateAll(o, g, oth) {
    const num = '' + o + g + oth;
    const sym = toBits(o) + toBits(g) + toBits(oth);
    document.getElementById('resNum').textContent = num;
    document.getElementById('resSym').textContent = sym;
    document.getElementById('resOct').textContent = '0' + num;
    document.getElementById('cmdN').textContent = num;
    document.getElementById('cmdNR').textContent = num;
    document.getElementById('bdO').textContent = o;
    document.getElementById('bdG').textContent = g;
    document.getElementById('bdOth').textContent = oth;
    document.getElementById('bdOD').textContent = bitDesc(o);
    document.getElementById('bdGD').textContent = bitDesc(g);
    document.getElementById('bdOthD').textContent = bitDesc(oth);
  }

  function setBoxes(o, g, oth) {
    document.getElementById('ur').checked = !!(o & 4);
    document.getElementById('uw').checked = !!(o & 2);
    document.getElementById('ux').checked = !!(o & 1);
    document.getElementById('gr').checked = !!(g & 4);
    document.getElementById('gw').checked = !!(g & 2);
    document.getElementById('gx').checked = !!(g & 1);
    document.getElementById('or').checked = !!(oth & 4);
    document.getElementById('ow').checked = !!(oth & 2);
    document.getElementById('ox').checked = !!(oth & 1);
  }

  function setDigits(o, g, oth) {
    document.getElementById('dO').value = o;
    document.getElementById('dG').value = g;
    document.getElementById('dOth').value = oth;
  }

  function syncFromDigits() {
    const o = clamp(parseInt(document.getElementById('dO').value));
    const g = clamp(parseInt(document.getElementById('dG').value));
    const oth = clamp(parseInt(document.getElementById('dOth').value));
    setBoxes(o, g, oth);
    updateAll(o, g, oth);
  }

  function syncFromBoxes() {
    const o = (document.getElementById('ur').checked?4:0)+(document.getElementById('uw').checked?2:0)+(document.getElementById('ux').checked?1:0);
    const g = (document.getElementById('gr').checked?4:0)+(document.getElementById('gw').checked?2:0)+(document.getElementById('gx').checked?1:0);
    const oth = (document.getElementById('or').checked?4:0)+(document.getElementById('ow').checked?2:0)+(document.getElementById('ox').checked?1:0);
    setDigits(o, g, oth);
    updateAll(o, g, oth);
  }

  function applyPreset(o, g, oth) {
    setDigits(o, g, oth);
    setBoxes(o, g, oth);
    updateAll(o, g, oth);
  }

  function doCopy(btn, text) {
    navigator.clipboard.writeText(text).catch(() => {});
    btn.textContent = 'copied!'; btn.classList.add('copied');
    setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('copied'); }, 2000);
  }

  // Clamp digit inputs on blur and handle arrow keys
  ['dO','dG','dOth'].forEach(id => {
    const el = document.getElementById(id);
    el.addEventListener('blur', () => {
      el.value = clamp(parseInt(el.value));
      syncFromDigits();
    });
    el.addEventListener('keydown', e => {
      if (e.key === 'ArrowUp') { e.preventDefault(); el.value = Math.min(7, parseInt(el.value||0)+1); syncFromDigits(); }
      if (e.key === 'ArrowDown') { e.preventDefault(); el.value = Math.max(0, parseInt(el.value||0)-1); syncFromDigits(); }
    });
  });

  // Init
  syncFromDigits();