【问题标题】:Useful BASH code snippets [closed]有用的 BASH 代码片段 [关闭]
【发布时间】:2010-11-01 05:28:09
【问题描述】:

我们已经为许多其他语言提供了这些。 C/C++ 的那个很受欢迎,Python 的等效项也是如此。我认为 BASH 的一个也会很有趣。

【问题讨论】:

  • 这应该是社区维基
  • 感谢您的指出!现在是。

标签: linux bash


【解决方案1】:

为了将 ~ 中由组 vboxusers 拥有的所有文件改为由用户组 kent 拥有,我创建了一些东西。但由于它在使用 xargs 方面存在弱点,因此我将其更改为对此答案的评论中提出的解决方案:

$ find ~ -group vboxusers -exec chown kent:kent {} \;

【讨论】:

  • 正确的做法是:find ~ -group vboxusers -exec chown kent:kent {} \;
  • 如果您有超过 4096 个结果,您的脚本将因 xargs 而失败。
  • 谢谢你的指出,我已经把上面的解决方案改成你的了。
【解决方案2】:

篇幅太长,无法全部包含,但How do I manipulate $PATH elements in shell scripts? 的解决方案对我来说非常有用...

【讨论】:

    【解决方案3】:

    生日,

    我最喜欢的,它适用于支持别名的其他 shell,是通过在命令前添加反斜杠来临时禁用别名的简单方法。

    所以:

    alias rm='rm -i'
    

    输入rm时总会给你交互模式,输入

    \rm
    

    在命令行上绕过别名。

    HTH

    干杯,

    【讨论】:

    • 非常重要。您始终可以使用 rm -f 覆盖它
    • @Chris,是的。不过,我对展示如何暂时禁用别名命令更感兴趣。 (-:
    【解决方案4】:

    这不是很有用,但真的很有趣:

    history | awk '{print $2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -n | tail | sort -nr
    

    它会打印 10 个最常用的命令。

    编辑:这个问题与this 非常相似。

    【讨论】:

      【解决方案5】:

      我们开发网站并将其代码存储在 SVN 中。当迁移到生产环境时,我们不希望 .svn 目录出现。以下代码递归目录并删除不需要的目录(可用于任何不需要的目录)。严格来说不是 bash,但仍然很有用。

      find . -type d -name .svn | xargs rm -rf
      

      从产品的最顶层路径执行...当然要小心,因为在错误的位置执行可能会导致非常糟糕的事情发生。

      您也可以通过将 -type d 更改为 -type f 来创建常规文件

      【讨论】:

      • 对于 svn 还有 svn export,它导出工作目录并保留 .svn 文件夹原样
      • 正确的做法是:find . -type d -name .svn -exec rm -rf {} \;
      • 如果您有超过 4096 个结果,您的脚本将因 xargs 而失败。
      【解决方案6】:

      在 BASH 脚本中,将参数分配给变量,但如果存在则提供默认值:

      MYVAR=${1:-default}
      

      $MYVAR 将包含第一个参数,否则为“默认”。

      【讨论】:

      • 更不用说这个 sn-p 的表亲了:MYVAR=${OTHER_VAR:=default} 如果未设置,它会将 OTHER_VAR 的值设置为默认值。以上仅使用默认值 仅在此实例中使用默认值,未设置 $1。
      【解决方案7】:

      要删除 .svn 目录,您还可以使用组合“find...-prune...-exec...”(不带 xargs):

      # tested on Mac OS X
      
      find -x -E . \( -type d -regex '.*/\.svn/*.*' -prune \) -ls  # test
      
      find -x -E . \( -type d -regex '.*/\.svn/*.*' -prune \) -exec /bin/rm -PRfv '{}' \; 
      

      【讨论】:

      • 我认为 gnu-find 不需要 -exec rm,因为有一个 -delete(但不确定 -PRfv :=verbose, force, Recursive, P?)。而且你不需要掩盖{} - 否则我很乐意在这里投票并接受它的答案:unix.stackexchange.com/q/8647/4485
      【解决方案8】:

      cd -可以进入之前访问过的目录:

      /usr/local/bin> cd /i/am/a/banana
      /i/am/a/banana> cd -
      /usr/local/bin>
      

      ...然后是 BASH for 循环的所有有用化身:

      for file in *.txt; do ls $file; done
      
      for item in $(echo foo bar baz); do echo $item; done
      
      for num in {0..9}; do echo $num; done
      

      【讨论】:

      • 我从来不知道cd -,谢谢!看起来它可能会有所帮助。
      • ick...我总是讨厌看到seq i jjot j i。现代 bash 有范围扩展: for n in {1..100};做...
      • 为什么会有一个名为 /i/am/a/banana 的目录? ;)
      • 避免使用反引号,并使用for item in $(echo foo bar baz),因为:a) $(..$(..)) 很容易嵌套,b) 取决于字体,反引号可能与撇号混淆,并且c) 你需要反引号在 SO 上的 cmets 中进行代码布局。
      【解决方案9】:

      很久以前在网上某处发现的:

      function bashtips {
      cat <<EOF
      DIRECTORIES
      -----------
      ~-      Previous working directory
      pushd tmp   Push tmp && cd tmp
      popd        Pop && cd
      
      GLOBBING AND OUTPUT SUBSTITUTION
      --------------------------------
      ls a[b-dx]e Globs abe, ace, ade, axe
      ls a{c,bl}e Globs ace, able
      \$(ls)      \`ls\` (but nestable!)
      
      HISTORY MANIPULATION
      --------------------
      !!      Last command
      !?foo       Last command containing \`foo'
      ^foo^bar^   Last command containing \`foo', but substitute \`bar'
      !!:0        Last command word
      !!:^        Last command's first argument
      !\$     Last command's last argument
      !!:*        Last command's arguments
      !!:x-y      Arguments x to y of last command
      C-s     search forwards in history
      C-r     search backwards in history
      
      LINE EDITING
      ------------
      M-d     kill to end of word
      C-w     kill to beginning of word
      C-k     kill to end of line
      C-u     kill to beginning of line
      M-r     revert all modifications to current line
      C-]     search forwards in line
      M-C-]       search backwards in line
      C-t     transpose characters
      M-t     transpose words
      M-u     uppercase word
      M-l     lowercase word
      M-c     capitalize word
      
      COMPLETION
      ----------
      M-/     complete filename
      M-~     complete user name
      M-@     complete host name
      M-\$        complete variable name
      M-!     complete command name
      M-^     complete history
      EOF
      }
      

      【讨论】:

        【解决方案10】:

        只有在设置了变量时才添加空格(或其他分隔符),以避免难看的不必要的空格。

        $ first=Joe
        $ last=      # last name blank, the following echoes a space before the period
        $ echo "Hello, $first $last. Welcome to..."
        Hello, Joe . Welcome to...
        
        $ echo "Hello, $first${last:+ $last}. Welcome to..."
        Hello, Joe. Welcome to...
        
        $ last=Green
        $ echo "Hello, $first${last:+ $last}. Welcome to..."
        Hello, Joe Green. Welcome to...
        

        【讨论】:

          【解决方案11】:
          : > truncate-file-to-zero-bytes.txt    # without changing its permissions  
          

          参见:coden-ps.joyent.com/posts/show/2067

          【讨论】:

            【解决方案12】:

            这是另一个:

            #!/bin/bash
            
            # Shows the full path of files, good for copy pasting and for when
            # listing the full paths is necessary.
            
            # Usage: Run in the working directory (no path), otherwise takes the
            # same file specification as ls.
            
            for file in $(ls "$@"); do
                    echo -n $(pwd)
                    [[ $(pwd) != "/" ]] && echo -n /
                    echo $file
            done
            

            【讨论】:

            • 短:readlink -f somefile
            【解决方案13】:

            必须以 root 身份运行的脚本的开头:

            if [ `id -u` != 0 ]; then
               echo "This script must be run as root" 1>&2
               exit 1
            fi
            

            【讨论】:

            • 不错的一个!我一直想知道如何从脚本中检测 root。 :-)
            • != 0是多余的,可以简写为test $(id -u) &amp;&amp; echo "This ..." &amp;&amp; exit 1
            • @userunknown:那行没有意义。 id -u 不会使用用户 ID 回答,并且无论退出状态为 0。除非您以某种方式使用 0 的根 ID 作为状态...这就是 1>&2... 在这个有趣的情况下...我检查了
            • ... 实际上,如果您不关心使用 bashisms... 您也可以这样写。 (( `id -u` )) &amp;&amp; echo "Must be root" &amp;&amp; exit 1
            【解决方案14】:

            我使用它来将源代码缩进四个空格并将结果复制到 X 中的剪贴板:

            cat src/Something.java | sed -e 's/^/    /g' | xsel
            

            现在Something.java 已准备好通过单击鼠标中键进行粘贴。我知道我可以将表达式减少一个管道并移除猫,但我喜欢这种方式,因为我发现在重新使用表达式时更容易编辑开头。

            【讨论】:

              【解决方案15】:

              在给定文件的情况下,一种有效(且直观)的方式来获取完整的规范文件路径。这将解决所有符号链接、相对文件引用等情况。

              full_path="$(cd $(/usr/bin/dirname "$file"); pwd -P)/$(/usr/bin/basename "$file")"
              

              【讨论】:

                【解决方案16】:

                我在 Java 开发中经常使用这个:

                #!/bin/sh 如果 [ "$1" == "" ] || [“$2”==“”];然后 echo "使用 jarfinder.sh" 出口 菲 搜索=`回显 $2 | sed -e 's/[\\\/]/./g'` echo 在 $1 中为“$SEARCH”搜索 jars 和 zips 查找 $1 -type f -printf "'%p'\n" | egrep "\.(jar|zip)'$" | sed -e "s/\(.*\)/echo \1 ; jar tvf \1 | sed -e 's\/^\/ \/' | grep -i \"$SEARCH\"/" |嘘

                我保存在我的collection of handy scripts 中。

                我也经常使用这种单线:

                find . -name "*.java" | xargs grep -li "yadayada"
                

                结束这个:

                find . -name "*.java" | sed -e 's+\(.*\)+echo \1 ; yada_cmd \1+' | sh
                

                【讨论】:

                  【解决方案17】:

                  这是一个很好的grep 表达式,用于删除空行和注释行:

                  grep -v '^[ \t]*$\|^[ \t]*#' /etc/ssh/sshd_config
                  

                  上面将在sshd_config中显示使用的设置,没有任何混乱。

                  【讨论】:

                    【解决方案18】:

                    我用它在自己的 xterm 窗口中(或不在)从同一个链接启动应用程序。

                    #!/bin/bash
                    #
                    # cli_app launcher -- detects where u are launching from;  gui/tty
                    # 
                    
                    dev=`/usr/bin/tty`
                    case $dev in
                    /dev/pts/0 | /dev/pts/1) xterm -e /home/user/bin/cli_app ;; ## opens gui terminal
                    *) /home/user/bin/cli_app ;;                                 ## opens where u are
                    esac
                    
                    # eof #
                    

                    【讨论】:

                      【解决方案19】:
                       !find:p  ......... show last find command - not execute
                       # create one dir and go to
                       echo 'mkcd() { mkdir -p "$@" && cd $_; }' >> ~/.bashrc  
                      
                       # backup file in single command
                       cp /path/too/long/to/file{,.backup}
                      

                      【讨论】:

                        【解决方案20】:

                        如果您希望在提示符 ($PS1) 中包含当前工作目录,在只有 80 列的终端中运行,并且有时在非常深的层次结构中工作,您最终会得到一个提示,除了大约 5 个字符。在这种情况下,以下声明很有帮助:

                        PS1='${PWD##$PREFIX}$ '
                        
                        PREFIX='' export PREFIX
                        prefix () {
                          PREFIX="$1"
                        }
                        prefix '*/'
                        

                        prefix '*/' 调用会将您的提示设置为仅包含当前工作目录的最后一个目录元素(而不是完整路径)。如果您想查看整个路径,请在不带参数的情况下调用 prefix

                        【讨论】:

                          【解决方案21】:

                          我喜欢反引号运算符。

                          gcc `pkg-config <package> --cflags` -o foo.o -c foo.c
                          

                          还有:

                          hd `whereis -b ls | sed "s/ls: //"` | head
                          

                          了解我,我错过了一种更有效的方法来“引导”二进制文件的 hexdump,而您不知道它的位置...哦,很明显,“ls”可以交换输出一个变量,所以在脚本中它会像这样:

                          #!/bin/bash
                          hd `whereis -b $1 | sed "s/$1: //"` | head
                          

                          以上内容的实际用途相当有限,但以我的拙见,它很好地展示了反引号运算符(和 bash shell)的多功能性。

                          【讨论】:

                            猜你喜欢
                            • 2010-10-01
                            • 2013-06-11
                            • 2013-05-13
                            • 1970-01-01
                            • 2010-09-08
                            • 2021-02-07
                            • 1970-01-01
                            • 2014-08-29
                            • 2011-11-24
                            相关资源
                            最近更新 更多