Mr Frog
Mr Frog

Reputation: 446

How can I list files from a ssh directory in R?

I know I can read files directly from ssh connections using pipe thanks to the the previous questions [1] and [2].
However I would like to read all the files with unknown names from such directories, and therefore I would need to use something such list.files() first on the ssh directory. Is it possible? How?

Upvotes: 2

Views: 309

Answers (2)

r2evans
r2evans

Reputation: 160862

Use the ssh package.

sess <- ssh::ssh_connect("[email protected]:22") # 22 is default, port not required unless different
aa <- ssh::ssh_exec_internal(sess, "ls -l /tmp/")
rawToChar(aa$stdout)
# [1] "total 3488\n-rw-rw-r--   1 myuser         myuser    508 Jan  4 05:38 exp\ndrwxr-xr-x 155 root           root    12288 Sep 12 13:14 quux\ndrwx------   3 root           root     4096 Dec 28 12:30 snap-private-tmp\ndrwx------   2 myuser         myuser   4096 Dec 28 12:34 tmux-1000\n"

If you don't care about the file metdata, then use a different command.

ab <- ssh::ssh_exec_internal(sess, "ls /tmp/")
rawToChar(ab$stdout)
# "exp\nquux\nsnap-private-tmp\ntmux-1000"

You can generally trust splitting on "\n" unless you know some remote filenames might be nefarious/untrusted. If you want to be more secure about it, or if you need more filtering or conditioning than ls alone can provide, then you can use find and its -print0, though rawToChar won't work so it requires a little more work.

split(ac$stdout, cumsum(ac$stdout == as.raw(0))) |>
  sapply(function(z) rawToChar(if (z[1] == as.raw(0)) z[-1] else z))
#                       0                       1                       2                       3                       4 
#                 "/tmp/"              "/tmp/exp"             "/tmp/quux"        "/tmp/tmux-1000" "/tmp/snap-private-tmp" 

We split the raw vector based on the presence of 00 (null byte). However, since the first null-byte will be found as the first byte in the second and subsequent list-elements after split (not the first list-element), we need to conditionally remove it before converting the remaining raw bytes to a string.

It might be useful to know the arguments for find such as -type f (not shown) and -maxdepth 1. See man find.

Upvotes: 0

Z&#233; Loff
Z&#233; Loff

Reputation: 1712

You can call ssh directly using system2, specifying ls as one of its arguments, and storing its output. E.g.:

system2('ssh', args = c('1.2.3.4', 'ls'), stdout = TRUE)

Replace 1.2.3.4 with the target machine's IP address or hostname. In the example above, the target user's home folder is listed, but you can add a further argument with the desired path, e.g.:

args = c('1.2.3.4', 'ls', '/tmp')

ssh options, such as a different user or port, can be specified as arguments before the target machine's address, e.g.:

args = c('-l', 'other_user',
         '-p', 2222,
         '1.2.3.4',
         'ls', '/tmp')

Upvotes: 0

Related Questions