6

How can I list files recursively with the nu shell?

More specifically: All files, folders and everything else in a specified folder and every inner folder, recursively.

  1. I tried ls **, but that does not work.
  2. I googled, found ls **/**.rs on Coming from Bash and tried ls **/*. That seemed to work, but I had to learn the hard way that it lists only some files, not all. I don't know why. But I found an example where ls **/* | where name =~ 'xxx' found less than ls **/*xxx*. (I thought about including my example here, to show what is listed and what not. But the folder structure is too huge.)
  3. I cannot use ls **/*xxx* as I do not want to filter by name every time. Sometimes I need to filter only by other columns.

(I hope the solution is OS independent. After all, the first advantage of nu praised on its homepage is: "Nu works on Linux, macOS, and Windows. Learn it once, then use it anywhere.")

NotTheDr01ds
  • 28,025

3 Answers3

3

I think we've determined at least two things in working through this in comments and chat:

  • ls -a should be used to make sure that files in hidden directories are included in the result.

  • There appears to currently be a bug in Nushell so that ls **/*abc* sometimes will return files in hidden directories that do not (oddly) match "abc" but will ignore files in hidden directories that do match. If anything, I'd expect the results to be reversed, but I'd really expect ls to always ignore files in hidden directories unless the -a flag is used.

    I've written up a Github issue on the topic.

So currently, to reliably return all files with "xxx" in the filename or path, use ls -a **/*xxx*.

If you want to return only files with "xxx" in the filename (but not any other part of the path), then:

ls -a **/*xxx* | where ($it.name | path basename) =~ 'xxx'

Note that the experimental Nushell glob command (in 0.61) will always return files in hidden directories using glob **/*xxx*, but it only returns filenames, and not in a Nushell column like ls, so it doesn't sound like it would work for your use case:

Sometimes I need to filter only by other columns

The same goes for ^find (not the built-in, but the binary).

However, please do be aware that using ls to return filenames for processing does have some limitations, at least with the present Nushell command:

  • There is currently no way to restrict results to a single filesystem, as with the ^find -xdev option.
  • Nushell's ls **/* will recursively follow symlinks. If you have something like ln -s .. parent, then ls will enter an infinite loop. find, by default, does not follow symlinks.

In general, I'd be very careful using ls **/... globs in current Nushell releases. The ^find binary is probably a safer option, at least for now.

NotTheDr01ds
  • 28,025
2

The bug mentioned in my original answer has been resolved, so, to recursively list all (non-hidden) files and subdirectories in all (non-hidden) subdirectories (tested on Nushell 0.76):

ls **/*

To include hidden files:

ls -a **/*

Pattern matching also works correctly. E.g.:

ls **/*.rs

To list recursively list directory names, but not the files within them:

ls **/**
NotTheDr01ds
  • 28,025
-2
find ./*

or install

tree

"Body must be at least 30 characters; you entered 24."

mitts
  • 162