shellsyntax-errornushell

Cannot rewrite some function from bash to nushell


I'm moving from bash to nushell. One of my steps was moving this function:

ex ()
{
  if [ -f $1 ] ; then
    case $1 in
      *.tar.bz2)   tar xjf $1   ;;
      *.tar.gz)    tar xzf $1   ;;
      *.bz2)       bunzip2 $1   ;;
      *.rar)       unrar x $1     ;;
      *.gz)        gunzip $1    ;;
      *.tar)       tar xf $1    ;;
      *.tbz2)      tar xjf $1   ;;
      *.tgz)       tar xzf $1   ;;
      *.zip)       unzip $1     ;;
      *.Z)         uncompress $1;;
      *.7z)        7z x $1      ;;
      *)           echo "'$1' cannot be extracted via ex()" ;;
    esac
  else
    echo "'$1' is not a valid file"
  fi
}

In nushell I wrote this:

def ex [$file?: string] {
        if $file == null {"No file defined"} else {
                if $file == *.tar.bz2 {
                        tar xjf $file;
                }
                else if $file == *.tar.gz {
                        tar xzf $file;
                }
                else if $file == *.bz2 {
                        bunzip2 $file;
                }
                else if $file == *.rar {
                        unzip $file;
                }
                else if $file == *.gz {
                        gunzip $file;
                }
                else if $file == *.tar {
                        tar xf $file;
                }
                else if $file == *.tbz2 {
                        tar xjf $file;
                }
                else if $file == *.tgz {
                        tar xzf $file;
                }
                else if $file == *.zip {
                        unzip $file;
                }
                else if $file == *.Z {
                        uncompress $file;
                }
                else if $file == *.7z {
                        7z x $file;
                }
        }
}

But when I tested it by this command(I had an openssl source code archive in a directory I was executing command from): ex openssl-1.1.1.tar.gz, I got this error: `

ex openssl-1.1.1.tar.gz                                                                                          
Error: nu::shell::external_command (link)

  × External command failed
     ╭─[/home/ysyltbya/.config/nushell/config.nu:523:1]
 523 │          }
 524 │          else if $file == *.tar.gz {
     ·   ──┬─
     ·     ╰── did you mean 'ls'?
 525 │                  tar xzf $file;
     ╰────
  help: No such file or directory (os error 2)

I can't understand what the problem is.


Solution

  • The main issue is that you are still attempting to use the Bash patterns for string matching. You can accomplish this in Nushell with either:

    However, you might consider a more functional/data-driven/Nushell-way of doing it:

    def ex [$file?: string] {
        let archivers = [
            [ pattern         , command              , options       ];
            [ ".tar.bz2"      , "tar"                , "xjf"         ]
            [ ".tar.gz"       , "tar"                , "xzf"         ]
            [ ".bz2"          , "unzip2"             , ""            ]
            [ ".tar.bz2"      , "tar"                , "xjf"         ]
            [ ".rar"          , "unrar"              , ""            ]
            [ ".gz"           , "gunzip"             , ""            ]
            [ ".tar"          , "tar"                , "xf"          ]
            [ ".tbz2"         , "tar"                , "xjf"         ]
            [ ".tgz"          , "tar"                , "xzf"         ]
            [ ".zip"          , "unzip"              , ""            ]
            [ ".Z"            , "uncompress"         , ""            ]
            [ ".7z"           , "7z"                 , "x"           ]
        ]
    
        if $file == null {
            print -e "No file defined"
        } else if not ($file | path exists) {
            print -e $"Can't find ($file)"
        } else {
            let matchingArchivers = ($archivers | where { |archiver| $file ends-with $archiver.pattern })
            if ($matchingArchivers | length) > 0 {
                let archiver = $matchingArchivers.0
                run-external $archiver.command $archiver.options $file
            } else {
                print -e $"($file) cannot be extracted via ex\(\)"
            }
        }
    }
    

    Notes: