【问题标题】:fish shell: Is it possible to conveniently strip extensions?fish shell:是否可以方便地剥离扩展?
【发布时间】:2015-06-03 09:17:27
【问题描述】:

有什么方便的方法可以从文件名中去除任意扩展名,比如 bash ${i%%.*}?我会坚持我的朋友sed吗?

【问题讨论】:

    标签: fish


    【解决方案1】:

    如果您知道扩展名(例如 _bak,一个常见的用例),这可能更方便:

    for f in (ls *_bak)
        mv $f (basename $f _bak)
    end
    

    【讨论】:

      【解决方案2】:

      不。 fish 的功能集比 bash 小得多,依赖于外部命令:

      $ set filename foo.bar.baz
      $ set rootname (echo $filename | sed 's/\.[^.]*$//')
      $ echo $rootname
      foo.bar
      

      【讨论】:

      • 谢谢,这就是我的怀疑。很好,您发布了解决方法:)
      • 如下所述,使用fish'string命令可以在不使用外部命令的情况下达到相同的效果。
      • 小心,因为 sed 正则表达式不处理特殊情况,例如:/this/is.another/test 给出 /this/is
      【解决方案3】:

      您可以使用string 命令从文件名中去除扩展名:

      echo (string split -r -m1 . $filename)[1]
      

      这将在最右边的点处拆分filename 并打印结果列表的第一个元素。如果没有点,则该列表将包含一个带有 filename 的元素。

      如果您还需要剥离前导目录,请将其与 basename 结合起来:

      echo (basename $filename | string split -r -m1 .)[1]
      

      在本例中,string 从标准输入读取其输入,而不是将文件名作为命令行参数传递。

      【讨论】:

      • 您也可以使用选项--field (-f) 来选择第一个字段,而不是使用[1]。示例:string split --right --max 1 --field 1 . $filename;另外我认为你不需要echo,因为string split 已经打印输出了。
      • 当文件名没有分机时,小心,因为这会在文件路径的最后一个点分割,例如:/this/is.another/test 给出/this/is
      【解决方案4】:

      使用鱼内置的string match 函数,您可以做到

      set rootname (string match -r "(.*)\.[^\.]*\$" $filename)[2]
      

      字符串匹配返回一个包含 2 个项目的列表。第一个是整个字符串,第二个是第一个正则表达式匹配(正则表达式括号内的东西)。所以,我们用 [2] 抓取第二个。

      【讨论】:

      • 小心,因为这会删除文件名上最后一个点之后没有分机的任何内容,例如:/this/is.another/test 给出/this/is
      【解决方案5】:

      fishstring 命令仍然是处理此问题的规范方法。它有一些非常好的子命令,尚未在其他答案中显示。

      split 允许您从右侧拆分,最大值为 1,这样您就可以得到最后一个扩展名。

      for f in *
          echo (string split -m1 -r '.' "$f")[1]
      end
      

      replace 允许您使用正则表达式来删除扩展名,定义为字符串末尾的最后一个点

      for f in *
          string replace -r '\.[^\.]*$' '' "$f"
      end
      

      man string 了解更多信息和一些很好的例子。

      -- 更新--

      如果您的系统有正确的basenamedirname 实用程序,您可以使用这样的工具:

      function stripext \
          --description "strip file extension"
      
          for arg in $argv
              echo (dirname $arg)/(string replace -r '\.[^\.]+$' '' (basename $arg))
          end
      end
      

      【讨论】:

      • 小心,因为这会删除文件名最后一个点之后没有分机的任何内容,例如:/this/is.another/test 给出/this/is
      • @NinjaInc - 这就是为什么我很高兴终于看到 path 实用程序进入 Fish:github.com/fish-shell/fish-shell/pull/8265
      【解决方案6】:

      我也需要一个函数来拆分随机文件的根目录和扩展名。与其冒着遇到警告的风险(例如:分隔符前的点)天真地重新实现该功能,我将任务转发给 Python 的内置 POSIX path 库并继承他们的专业知识。

      下面是一个简单的例子,说明人们可能更喜欢什么:

      function splitext --description "Print filepath(s) root, stem or extension"
      
          argparse 'e/ext' 's/stem' -- $argv
      
          for arg in $argv
              if set -q _flag_ext
                  set cmd 'import os' \
                          "_, ext = os.path.splitext('$arg')" \
                          'print(ext)'
              else if set -q _flag_stem
                  set cmd 'from pathlib import Path' \
                          "p = Path('$arg')" \
                          'print(p.stem)'
              else
                  set cmd 'import os' \
                          "root, _ = os.path.splitext('$arg')" \
                          'print(root)'
              end
              python3 -c (string join ';' $cmd)
          end
      
      end
      

      例子:

      $ splitext /this/is.a/test.path
      /this/is.a/test
      $ splitext --ext /this/is.a/test.path
      .path
      $ splitext --stem /this/is.a/test.path
      test
      $ splitext /this/is.another/test
      /this/is.another/test
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-28
        • 1970-01-01
        • 2010-12-21
        • 1970-01-01
        • 2010-12-24
        • 1970-01-01
        • 1970-01-01
        • 2017-09-11
        相关资源
        最近更新 更多