aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--nnn.13
-rw-r--r--nnn.c26
3 files changed, 25 insertions, 6 deletions
diff --git a/README.md b/README.md
index c7fd3e3..4f0f72d 100644
--- a/README.md
+++ b/README.md
@@ -389,6 +389,8 @@ To wrap each file path within single quotes, export `NNN_QUOTE_ON`:
export NNN_QUOTE_ON=1
This is particularly useful if you are planning to copy the whole string to the shell to run a command. Quotes can be toggled at runtime using <kbd>^T</kbd>.
+Note that the filename is not escaped. So copying may still fail for filenames having quote(s) in them.
+
#### copy file paths when X is missing
A very common scenario on headless remote servers connected via SSH. As the clipboard is missing, `nnn` copies the path names to the tmp file `/tmp/nnncp$USER`.
diff --git a/nnn.1 b/nnn.1
index f44281f..e420593 100644
--- a/nnn.1
+++ b/nnn.1
@@ -263,7 +263,8 @@ screensaver.
.Ed
.Pp
\fBNNN_QUOTE_ON:\fR wrap copied paths within single quotes. Useful for pasting
-names in the shell.
+names in the shell. Note that the filename is not escaped. So copying may still fail
+for filenames having quote(s) in them.
.Pp
\fBNNN_SCRIPT:\fR path to a custom script to invoke with currently selected file name as argument 1.
.Bd -literal
diff --git a/nnn.c b/nnn.c
index 3e90509..0e5e5ea 100644
--- a/nnn.c
+++ b/nnn.c
@@ -1752,6 +1752,19 @@ xgetgrgid(gid_t gid)
return grp->gr_name;
}
+static bool
+istgtdir(const char *tgtpath)
+{
+ if (tgtpath) {
+ struct stat tgtsb;
+ int r = stat(tgtpath, &tgtsb);
+ if ((r == 0) && (tgtsb.st_mode & S_IFMT) == S_IFDIR)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/*
* Follows the stat(1) output closely
*/
@@ -1772,16 +1785,19 @@ show_stats(char *fpath, char *fname, struct stat *sb)
/* Show file name or 'symlink' -> 'target' */
if (perms[0] == 'l') {
/* Note that MAX_CMD_LEN > PATH_MAX */
- ssize_t len = readlink(fpath, g_buf, MAX_CMD_LEN);
-
- if (len != -1) {
- g_buf[len] = '\0';
+ char *tgt = realpath(fpath, g_buf);
+ if (tgt) {
+ char ch[] = {'\'', '\0', '\0'};
+ if (istgtdir(g_buf)) {
+ ch[1] = ch[0];
+ ch[0] = '/';
+ }
/*
* We pass g_buf but unescape() operates on g_buf too!
* Read the API notes for information on how this works.
*/
- dprintf(fd, " -> '%s'", unescape(g_buf, 0));
+ dprintf(fd, " -> '%s%s", unescape(g_buf, 0), ch);
}
}