Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash Can';我不能让这个代码工作_Bash_Shell - Fatal编程技术网

Bash Can';我不能让这个代码工作

Bash Can';我不能让这个代码工作,bash,shell,Bash,Shell,我正在编写一个bash shell脚本,它使用了一个带有三个选项的case: 如果用户输入“change-r txt doc*”,则子目录中的文件扩展名将发生更改 如果用户输入“change-n-r doc”,则应重命名以-r或-n结尾的文件(这将把当前名为*.r的目录中的所有文件重命名为*.doc) 如果用户不输入任何内容,如“change txt doc*”,它只会更改当前目录中的文件扩展名 以下是我为其生成的代码(最后两个选项,我不确定如何实现): 有人能帮我修一下吗?或者至少告诉我哪里出

我正在编写一个bash shell脚本,它使用了一个带有三个选项的case:

  • 如果用户输入“change-r txt doc*”,则子目录中的文件扩展名将发生更改
  • 如果用户输入“change-n-r doc”,则应重命名以-r或-n结尾的文件(这将把当前名为*.r的目录中的所有文件重命名为*.doc)
  • 如果用户不输入任何内容,如“change txt doc*”,它只会更改当前目录中的文件扩展名
  • 以下是我为其生成的代码(最后两个选项,我不确定如何实现):


    有人能帮我修一下吗?或者至少告诉我哪里出了问题?

    你应该重温一下字符串替换。实际上是各种各样的。Bash很擅长这些。Bash食谱的第105页(配方5.18)是这方面的优秀读物

    #!/bin/bash
    
    # Make it more flexible for improving command line parsing later
    SWITCH=$1
    EXTENSIONSRC=$2
    EXTENSIONTGT=$3
    
    # Match different cases for the only allowed switch (other than file extensions)
    case $SWITCH in
     -r|--)
      # If it's not -r we limit the find to the current directory
      [[ "x$SWITCH" == "x-r" ]] || DONTRECURSE="-maxdepth 1"
      # Files in current folder with particular pattern (and subfolders when -r)
      find . $DONTRECURSE -iname "*.$EXTENSIONSRC"|while read fname; do
        # We use a while to allow for file names with embedded blank spaces
        # Get canonical name of the item into CFNAME
        CFNAME=$(readlink -f "$fname")
        # Strip extension through string substitution
        NOEXT_CFNAME="${CFNAME%.$EXTENSIONSRC}"
        # Skip renaming if target exists. This can happen due to collisions
        # with case-insensitive matching ...
        if [[ -f "$NOEXT_CFNAME.$EXTENSIONTGT" ]]; then
          echo "WARNING: Skipping $CFNAME"
        else
          echo "Renaming $CFNAME"
          # Do the renaming ...
          mv "$CFNAME" "$NOEXT_CFNAME.$EXTENSIONTGT"
        fi
      done
      ;;
     *)
      # The -e for echo means that escape sequences like \n and \t get evaluated ...
      echo -e "ERROR: unknown command line switch\n\tSyntax: change <-r|--> <source-ext> <target-ext>"
      # Exit with non-zero (i.e. failure) status
      exit 1
    esac
    
    #/bin/bash
    #使其更灵活,以便以后改进命令行解析
    开关=1美元
    扩展名rc=$2
    extensiongt=$3
    #为唯一允许的开关匹配不同的情况(文件扩展名除外)
    案例$SWITCH-in
    -r |--)
    #如果不是-r,我们将查找限制为当前目录
    [[“x$SWITCH”==“x-r”]| | DONTRECURSE=“-maxdepth 1”
    #当前文件夹中具有特定模式的文件(以及-r时的子文件夹)
    找到$DONTRECURSE-iname“*.EXTENSIONSRC”|同时读取fname;做
    #我们使用while来允许文件名中嵌入空格
    #将项的规范名称获取到CFNAME中
    CFNAME=$(readlink-f“$fname”)
    #通过字符串替换实现条带扩展
    NOEXT_CFNAME=“${CFNAME%.$EXTENSIONSRC}”
    #如果目标存在,则跳过重命名。这可能是由于碰撞造成的
    #使用不区分大小写的匹配。。。
    如果[-f“$NOEXT\u CFNAME.$extensiongt”];然后
    echo“警告:跳过$CFNAME”
    其他的
    echo“重命名$CFNAME”
    #进行重命名。。。
    mv“$CFNAME”$NOEXT\U CFNAME.$EXTENSIONGT”
    fi
    完成
    ;;
    *)
    #echo的-e表示像\n和\t这样的转义序列得到计算。。。
    echo-e“错误:未知命令行开关\n\t语法:更改”
    #以非零(即故障)状态退出
    出口1
    以撒
    
    脚本中显然给出了语法。我可以自由地使用
    --
    将命令行开关与文件名分离的约定。这样看起来更干净,实际上更容易实现

    NB:可以进一步浓缩。但在这里,我试图表达自己的观点,而不是赢得混乱的Bash竞赛;)


    PS:在重命名部分也处理不区分大小写的内容。但是,如果目标文件已经存在,我决定将其跳过。可能可以重写为命令行选项。

    代码有什么不起作用?@John,当我昨天运行它时(目前不在linux计算机附近),-r不会重命名文件扩展名。在“-n”(2)和“*”(3)选项中,我不知道如何编码。我需要帮助。@Deaths先生:你是说在各自的位置上有任何具有特定扩展名的文件吗?有一件事我真的不明白,
    -n-r
    ..-n和-r是它需要的参数。因此,如果您输入“change-r txt doc*”(注意-r),它会这样做:“文件扩展名在子目录中被更改。”如果您输入“change-n-r doc”(注意-n),它会这样做:“重命名以-r或-n结尾的文件(这会将当前目录中名为*.r或*.n的所有文件重命名为*.doc)”@Mr teaths:正确的方法是遵循GNU标准解析命令行开关;)。。。使用
    --
    将开关与文件名分开。正在开发一个小版本,至少可以让您开始。谢谢,但是您的代码太复杂了。你必须明白我仍然是bashshell脚本的新手。有没有更简单的方法可以实现这一点?这是我写的一段旧代码,与之类似。你能实现我想在里面做的吗/bin/sh#$1扩展名要重命名#$2为新扩展名EXTf=$1 EXTt=$2,而测试Z$3!=Z do NAME=$3 echo$NAME new=
    basename$NAME.$EXTf
    echo$new mv$new.$EXTf$new.$EXTt shift请给我您的电子邮件地址,让我解释一下我想做得更好。@齿先生:对不起,不会在这样的开放位置提供它。代码有什么这么复杂?我应该多加评论吗?这不是问题,但我想你会知道基本的。@SAD,非常感谢你添加额外的评论,我可以理解你现在想做什么。最后一个版本是一个复杂的版本。这更清楚。不要担心电子邮件的事。这里有私人信息系统吗?@teots先生:不要认为有PM设施,尽管那会很酷。很高兴现在对你有用。如果你对剧本的某些部分有疑问,尽管问。
    #!/bin/bash
    
    # Make it more flexible for improving command line parsing later
    SWITCH=$1
    EXTENSIONSRC=$2
    EXTENSIONTGT=$3
    
    # Match different cases for the only allowed switch (other than file extensions)
    case $SWITCH in
     -r|--)
      # If it's not -r we limit the find to the current directory
      [[ "x$SWITCH" == "x-r" ]] || DONTRECURSE="-maxdepth 1"
      # Files in current folder with particular pattern (and subfolders when -r)
      find . $DONTRECURSE -iname "*.$EXTENSIONSRC"|while read fname; do
        # We use a while to allow for file names with embedded blank spaces
        # Get canonical name of the item into CFNAME
        CFNAME=$(readlink -f "$fname")
        # Strip extension through string substitution
        NOEXT_CFNAME="${CFNAME%.$EXTENSIONSRC}"
        # Skip renaming if target exists. This can happen due to collisions
        # with case-insensitive matching ...
        if [[ -f "$NOEXT_CFNAME.$EXTENSIONTGT" ]]; then
          echo "WARNING: Skipping $CFNAME"
        else
          echo "Renaming $CFNAME"
          # Do the renaming ...
          mv "$CFNAME" "$NOEXT_CFNAME.$EXTENSIONTGT"
        fi
      done
      ;;
     *)
      # The -e for echo means that escape sequences like \n and \t get evaluated ...
      echo -e "ERROR: unknown command line switch\n\tSyntax: change <-r|--> <source-ext> <target-ext>"
      # Exit with non-zero (i.e. failure) status
      exit 1
    esac