Search code examples
nushell

Create new column base upon existing column in NuShell


I am new to NuShell and would like to create a quick way to locate my files by their "tags", which are in the filename. This is the method used by tagspaces. For instance, using the ls command my directory might look like this:

# name type size modified
0 Documents dir 134 b a week ago
1 Fake doc1 [Fake clj client project1].txt file 15 B 2 weeks ago
2 Downloaded_doc.pdf file 150 B 4 weeks ago
3 Fake doc2 [Important :12/31/2022 client project1].txt file 365 B 1 week ago

However, I would like to create a new column labeled "tags" and only include the tags (the terms inside the brackets) from the name column. I think this regex will take the bracketed information (includes brackets at this point, which I don't want: \[.+?\]

I would like the end result to look like this:

# name tags type size modified
0 Documents dir 134 b a week ago
1 Fake doc1 [Fake clj client project1].txt Fake clj client project1 file 15 B 2 weeks ago
2 Downloaded_doc.pdf file 150 B 4 weeks ago
3 Fake doc2 [Important :12/31/2022 client project1].txt Important :12/31/2022 client project1 file 365 B 1 week ago

What would be the best way of doing this? I have read the docs but need to see more real life code before I really "get" this shell.

Thank you!


Solution

  • $ ls | insert tags {|item|
        if $item.name =~ '\[.*\]' {
          $item.name | str replace '.*\[(.*)\].*' '$1'
        }
      } | move tags --after name
    
    ╭───┬───────────────────────────────────────────────────────┬───────────────────────────────────────┬──────┬─────────┬───────────────╮
    │ # │                         name                          │                 tags                  │ type │  size   │   modified    │
    ├───┼───────────────────────────────────────────────────────┼───────────────────────────────────────┼──────┼─────────┼───────────────┤
    │ 0 │ Documents                                             │                                       │ dir  │ 4.0 KiB │ 9 minutes ago │
    │ 1 │ Downloaded_doc.pdf                                    │                                       │ file │     0 B │ 9 minutes ago │
    │ 2 │ Fake doc1 [Fake clj client project1].txt              │ Fake clj client project1              │ file │     0 B │ 9 minutes ago │
    │ 3 │ Fake doc2 [Important :12-31-2022 client project1].txt │ Important :12-31-2022 client project1 │ file │     0 B │ 8 minutes ago │
    ╰───┴───────────────────────────────────────────────────────┴───────────────────────────────────────┴──────┴─────────┴───────────────╯
    
    • The insert built-in creates a new column

    • It takes a closure, which runs on each item in the table. The value of $item becomes each directory entry.

    • All we really care about here is the $item.name. First we test it to see if it has tags in the [] format.

    • If it does, we set the tags column value to the text matching inside the [].

      This might be a bit tricky to parse at first, but keep in mind that the last value (in this case the only value) in the closure or block is essentially its "return value". There's no need to echo or return it, since Nushell has implicit output.

      For instance, if that line was simply the string "Has tags", then the tags column would include that string (rather than the actual matched tags) for each directory entry that matched the if statement.

    • Finally, after the tags column has been inserted, we move it directly after the name column.