diff options
| author | 2019-11-20 01:28:11 +0530 | |
|---|---|---|
| committer | 2019-11-20 01:28:11 +0530 | |
| commit | 3a9def25d815dae7a7db658d2383004417116fb6 (patch) | |
| tree | f99d4caf81f236ffcdc336a81775886010268c7c | |
| parent | 9729b1f5a60d612e173695f3e3a997a44f5d7a94 (diff) | |
| download | nnn-3a9def25d815dae7a7db658d2383004417116fb6.tar.gz | |
Create new files and dirs with parent (like mkdir -p)
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | src/nnn.c | 67 |
2 files changed, 62 insertions, 7 deletions
@@ -56,7 +56,7 @@ Add to that an awesome [Wiki](https://github.com/jarun/nnn/wiki)! - Cross-dir file/all/range selection - Batch rename selection or dir entries - Copy (as), move (as), delete, archive, link selection - - Create, rename, duplicate files and dirs + - Create (with parents), rename, duplicate (anywhere) files and dirs - Spawn a shell, run apps, run commands, execute file - Lock terminal (needs a locker) - Minimal deps, minimal config @@ -1317,6 +1317,59 @@ static void xrm(char *path) } } +/* Create non-existent parents and a file or dir */ +static bool xmkentryp(char* path, bool dir) +{ + char* p = path; + char *slash = path; + + if (!p || !*p) + return FALSE; + + /* Skip the first '/' */ + ++p; + + while (*p != '\0') { + if (*p == '/') { + slash = p; + *p = '\0'; + } else { + ++p; + continue; + } + + /* Create folder from path to '\0' inserted at p */ + if (mkdir(path, 0777) == -1 && errno != EEXIST) { + DPRINTF_S("mkdir1 fail"); + DPRINTF_S(strerror(errno)); + *slash = '/'; + return FALSE; + } + + /* Restore path */ + *slash = '/'; + ++p; + } + + if (dir) { + if(mkdir(path, 0777) == -1 && errno != EEXIST) { + DPRINTF_S("mkdir2 fail"); + DPRINTF_S(strerror(errno)); + return FALSE; + } + } else { + int fd = open(path, O_CREAT, 0666); + if (fd == -1 && errno != EEXIST) { + DPRINTF_S("open fail"); + DPRINTF_S(strerror(errno)); + return FALSE; + } else + close(fd); + } + + return TRUE; +} + static uint lines_in_file(int fd, char *buf, size_t buflen) { ssize_t len; @@ -4834,7 +4887,8 @@ nochange: break; /* Allow only relative, same dir paths */ - if (tmp[0] == '/' || xstrcmp(xbasename(tmp), tmp) != 0) { + if (tmp[0] == '/' + || ((r != 'f' && r != 'd') && (xstrcmp(xbasename(tmp), tmp) != 0))) { printwait(messages[STR_INPUT_ID], &presel); goto nochange; } @@ -4929,11 +4983,12 @@ nochange: } else { /* Check if it's a dir or file */ if (r == 'f') { - r = openat(fd, tmp, O_CREAT, 0666); - close(r); - } else if (r == 'd') - r = mkdirat(fd, tmp, 0777); - else if (r == 's' || r == 'h') { + mkpath(path, tmp, newpath); + r = xmkentryp(newpath, FALSE); + } else if (r == 'd') { + mkpath(path, tmp, newpath); + r = xmkentryp(newpath, TRUE); + } else if (r == 's' || r == 'h') { if (tmp[0] == '@' && tmp[1] == '\0') tmp[0] = '\0'; r = xlink(tmp, path, newpath, &presel, r); |