在Bash中更改带下划线的空格

在Bash中更改带下划线的空格,bash,Bash,我想用Bash编写一个脚本: 将文件作为输入 如果文件名有任何空格,则会用下划线将其更改 我的第一个问题是:Bash脚本能否将参数作为输入,或者一旦脚本通过read命令运行,就必须提供任何输入?另一个问题是如何使用mv命令执行第2点。您的脚本可以是: #!/bin/bash mv "$1" "$(sed 's/ \{1,\}/_/g' <<<"$1")" 这种方法的行为略有不同,因为它将用下划线替换每个单独的空格,而使用sed的方法也将空格组压成一个下划线。如果启用扩展全局

我想用Bash编写一个脚本:

  • 将文件作为输入

  • 如果文件名有任何空格,则会用下划线将其更改


  • 我的第一个问题是:Bash脚本能否将参数作为输入,或者一旦脚本通过read命令运行,就必须提供任何输入?另一个问题是如何使用
    mv
    命令执行第2点。

    您的脚本可以是:

    #!/bin/bash
    
    mv "$1" "$(sed 's/ \{1,\}/_/g' <<<"$1")"
    
    这种方法的行为略有不同,因为它将用下划线替换每个单独的空格,而使用sed的方法也将空格组压成一个下划线。如果启用扩展全局绑定,则可以使此版本的行为与使用sed的版本相同:

    shopt -s extglob
    mv "$1" "${1//+( )/_}"
    

    根据您是要替换空格字符
    还是所有类型的空格(如制表符、换行符等),您可能希望在这些示例中使用
    [[:space:]
    而不是

    您的脚本可以是:

    #!/bin/bash
    
    mv "$1" "$(sed 's/ \{1,\}/_/g' <<<"$1")"
    
    这种方法的行为略有不同,因为它将用下划线替换每个单独的空格,而使用sed的方法也将空格组压成一个下划线。如果启用扩展全局绑定,则可以使此版本的行为与使用sed的版本相同:

    shopt -s extglob
    mv "$1" "${1//+( )/_}"
    

    根据您是要替换空格字符
    还是所有类型的空格(如制表符、换行符等),您可能希望在这些示例中使用
    [[:space:]
    而不是

    是的,当然可以为bash脚本提供参数。我建议至少阅读一下bash手册(manbash),它将回答您的大多数问题

    Re:你的实际任务——了解你的操作系统真的很有帮助。如果您在*nix上运行此操作,则以下类似操作将解决您的问题:

    $ touch "example file 1" "example  file  2"
    $ ls -ld example*
    -rw------- 1 user group 0 Oct 29 00:06 example  file  2
    -rw------- 1 user group 0 Oct 29 00:06 example file 1
    $ find . -maxdepth 1 -type f -name '* *' -print0 | xargs -0i /bin/bash -c 'F="{}" ; mv -iv "$F" "${F//[[:space:]]/_}"'
    './example  file  2' -> './example__file__2'
    './example file 1' -> './example_file_1'
    $ ls -ld example*
    -rw------- 1 user group 0 Oct 29 00:06 example__file__2
    -rw------- 1 user group 0 Oct 29 00:06 example_file_1
    $
    

    是的,当然可以为bash脚本提供参数。我建议至少阅读一下bash手册(manbash),它将回答您的大多数问题

    Re:你的实际任务——了解你的操作系统真的很有帮助。如果您在*nix上运行此操作,则以下类似操作将解决您的问题:

    $ touch "example file 1" "example  file  2"
    $ ls -ld example*
    -rw------- 1 user group 0 Oct 29 00:06 example  file  2
    -rw------- 1 user group 0 Oct 29 00:06 example file 1
    $ find . -maxdepth 1 -type f -name '* *' -print0 | xargs -0i /bin/bash -c 'F="{}" ; mv -iv "$F" "${F//[[:space:]]/_}"'
    './example  file  2' -> './example__file__2'
    './example file 1' -> './example_file_1'
    $ ls -ld example*
    -rw------- 1 user group 0 Oct 29 00:06 example__file__2
    -rw------- 1 user group 0 Oct 29 00:06 example_file_1
    $
    

    请用Bash<代码>mv“$1”“${1/[:space:][]/}”。无需为此开具
    sed
    。@gniourf\u gniourf将您的评论作为一个答案,以便我可以对其进行投票:)@gniourf\u gniourf,您的版本将很乐意替换其他空白字符。在我的回答中,我只是用相同的结构替换空格正如有人指出的,我错过了那个特别的要求,修正了我的答案。@galaxy:这不是OP的要求吗?如果文件名有任何空格,它会用下划线将其更改。@gniourf_gniourf,实际上RedX还没有在此处发布任何答案:)请使用Bash<代码>mv“$1”“${1/[:space:][]/}”。无需为此开具
    sed
    。@gniourf\u gniourf将您的评论作为一个答案,以便我可以对其进行投票:)@gniourf\u gniourf,您的版本将很乐意替换其他空白字符。在我的回答中,我只是用相同的结构替换空格正如有人指出的,我错过了那个特别的要求,修正了我的答案。@galaxy:这不是OP的要求吗?如果文件名有任何空格,它会用下划线将其更改。@gniourf_gniourf,实际上RedX还没有在此处发布任何答案:)您不需要
    xargs
    find-maxdepth 1-类型f-名称'**'-execdir bash-c'mv“$0”“${0//}”'{}\。(也使用了
    bash
    ,因为我的
    sh
    不支持此扩展)。@gniourf\u gniourf:是的,我支持,因为-execdir是GNU扩展,并且不在任何地方都可用,所以为了安全起见(OP没有提到它们运行的操作系统),我决定使用xargs:)--谢谢你指出re:sh,这是一个有效的观点。
    -execdir
    不是GNU扩展(你不是第一个声称这一点的人……这是从哪里得到的?)。无论如何,
    -exec
    也能完成这项工作。@gniourf_gniourf,嗯,我不能很快找到这方面的任何东西,但我记得在2005-2006年,有一些Linux发行版不支持-execdir,因此习惯:)。谢谢你的回答。当然,我的目的是阅读更多关于bash脚本的内容。您不需要
    xargs
    find-maxdepth 1-类型f-名称'**'-execdir bash-c'mv“$0”“${0//}”'{}\。(也使用了
    bash
    ,因为我的
    sh
    不支持此扩展)。@gniourf\u gniourf:是的,我支持,因为-execdir是GNU扩展,并且不在任何地方都可用,所以为了安全起见(OP没有提到它们运行的操作系统),我决定使用xargs:)--谢谢你指出re:sh,这是一个有效的观点。
    -execdir
    不是GNU扩展(你不是第一个声称这一点的人……这是从哪里得到的?)。无论如何,
    -exec
    也能完成这项工作。@gniourf_gniourf,嗯,我不能很快找到这方面的任何东西,但我记得在2005-2006年,有一些Linux发行版不支持-execdir,因此习惯:)。谢谢你的回答。当然,我的目的是阅读更多关于bash脚本的内容。