bash,如何围绕某些限制操作“ls”?

bash,如何围绕某些限制操作“ls”?

ls似乎有许多对我来说很奇怪的限制,这些限制未包含在其开关中(例如--max-depth=其他工具所具有的)。我喜欢维护通用标准(因此lsll遵循大多数普通发行版所具有的标准),但我的其他别名遵循某种易于记住的语法(lls“长列表、安全性”等)。我可以将其分成几个不同的问题,但由于这一切都与寻找通用操作方法的尝试有关ls,因此列出我的工作清单来描述我正在谈论的内容感觉更合适,因为它们都是相关的。一些具体问题:

  • 我经常听到有人说你永远不应该lsfor循环等中使用。这在默认情况下如何ls查看子目录等方面是有意义的,但是有没有一种简单的方法可以剪辑ls以从不查看子目录内部?我--max-depth=在页面中没有看到任何类似的内容man,但在我看来,如果我们剪辑ls不进入子目录,那么在for循环或其他结构中使用应该是可靠的。是否有一种可靠的方法来剪辑ls为仅一个目录的输出,然后在 for 循环中使用它?

  • 我使用了我认为相当笨重的结构lld(带有目录的长列表)和llf(带有文件的长列表)。有没有更好的方式来表达“我只想查看文件”?或“我只想查看目录?”;再次,man页面中我看不到任何内容 。特别是,我只能以-l格式进行此列表,否则我无法 grep 出我不想显示的项目。一般来说,我认为以这种方式使用 grep 可能是一个坏主意(因为锁定-l格式),那么有没有更好的方法来实现仅选择目录项或仅选择文件,而不是使用 grep ?

  • 如果下面的任何其他方法格式错误,我希望知道更好的方法?

尝试拥有一组标准的ls输出(每个发行版的设置通常不同)。

字符[]集通配符。例如ls name[03][17].c, 将匹配name01.c, name07.c, name31.c, name37.c, 并且[]还允许范围:ls name[07][1-9].c

请注意使用 来\ls运行裸命令,忽略别名。

-F一个指示符(其中之一*/=>@|)附加到条目 color=alwaysvscolor=auto

ls就递归而言非常尴尬,例如ls *即使没有标志,也会查看每个子文件夹-R,并且ls c*会查看每个文件夹c

ls切勿在 a 中使用 an 的输出,for i in ls因为这可能是不可预测的。

不想对别名做任何晦涩的事情,请遵循广泛使用的lsll、的设置l,然后为其他任务添加其他别名。

  • [[ $(type ls) == *"aliased"* ]] && then unalias ls:不需要这个,但一般来说是测试类型以alias对其采取行动

  • alias ls='\ls --color=always --group-directories-first':l将在大多数发行版中打印正常内容ls(即不会显示.*文件!)。请注意,\在命令恢复之前,命令会恢复其非别名形式。

  • alias l='ls -AFh --color=always --group-directories-first':使用-A(几乎所有,忽略./../,但显示所有.*文件,将其放在ls几乎总是想查看.*文件的位置)

  • alias la='ls -Ah': 长格式(-AFh以及-l):请注意,上面的l别名用于\ls运行 ls bare 而不带标志(主要是删除-A

  • alias ll='ls -lAh': 长格式(-AFh以及-l):请注意,上面的l别名用于在没有标志的情况下裸\ls运行ls-A主要是删除)

alias l.='ls -d .*'    # Explicitly list just .* files, so ./ and ../ are shown, overriding the A flag
alias ls.='ls -d .*'   # Explicitly list just .* files, so ./ and ../ are shown, overriding the A flag, long format
alias ll.='ls -dl .*'  # Explicitly list just .* files, so ./ and ../ are shown, overriding the A flag, long format
alias lld='ls -FlA | grep :*/'      # Only directories
alias llf='ls -FlA | grep -v "/"'   # Only files (broken as will show symlinks etc, if have to use `/`, then `/$` would be better, but using grep at all is probably not optimal)
alias ldot="ls -ld .??*"            # Dotfiles only
alias lx="ls -FlA | grep *"         # Executable files only, below 'lxext' is just trying to find 'executable-like' files by their extension
alias lnox="ls -FlA | grep -v *"    # Everything except executable files
alias lxext='ll *.sh *.csh *.ksh *.c *.cpp *.py *.jar *.exe *.bat *.cmd *.com *.js *.vbs *.wsh *.ahk *.ps1 *.psm1 2> /dev/null'  # List possible executables and scripts by extensions, discarding error output (as will generate for every type that is not there)
alias lext='ls -Fla | egrep "\."'         # Files without extensions only   ".|/"
alias lnoext='ls -Fla | egrep -v "\."'    # Files without extensions only
alias lsp='find . -maxdepth 1 -perm -111 -type f'        # List executable by permissions.   ls -lsa | grep -E "[d\-](([rw\-]{2})x){1,3}"   https://stackoverflow.com/q/7812324
alias lsum="ls -Fla \$1 \$2 \$3 \$4 \$5  | awk '{ print; x=x+\$5 } END { print \"total bytes = \",x }'"   # ls on required info then awk will sum the sizes
alias lll='ls --human-readable --size -1 -S --classify'  # Long-list with just size and name and total size summary line
alias lm='ls -Am'; alias lcsv='lm'         # comma separated view (-m), -A almost all, except '.' and '..'
alias lsz='ls -lAshSr'; alias lsize='lsz'  # -s size, -h human readable, -S by size, -r reverse so largest are easily visible at end
alias lt='ls -lAth'  ; alias ltime='lt'; alias ldate='lt'; alias lst='lt'   # sort by -t time/date, human readable
# replicate 'ls', but using 'stat' to show both normal 'ls' permission flags *and* octal.
lsec() { if [ -z "$@" ]; then args='. .*'; else args="$@"; fi; stat --printf="%A\t%a\t%h\t%U\t%G\t%s\t%.19y\t%n\n" $args; };   alias lstat='lsec';
lperm() { if [ -z "$@" ]; then args='. .*'; else args="$@"; fi; stat --printf="%A  %a  %n\n" $args; };   # Just permissions, %A (ls format), %a (Octal format) and names
sanitize() { chmod -R u=rwX,g=rX,o= "$@" ;}   # Make directory and file access rights the same
alias 000='echo "---------- (Owner -, Group -, and Other -)"; chmod 000'   # Remove permissions: append with file/directory to apply to
alias 644='echo "-rw-r--r-- (Owner rw, Group r, and Other r)"; chmod 644'  # Onwer rw, everyone else read-only
alias 755='echo "-rwxr-xr-x (Owner rwx, Group r-x, and Other r-x)"; chmod 755'  # Make executable, but only Owner has write permissions
alias mx='chmod a+x'   # Make Executable
alias lls='lss'        # Since the 'stat' output is in long format 'll', also use 'lls' for 'long listing with ecurity'
alias sl='ls'          # Common typo, also just overwrite the 'Steam Locotomive' toy if present, as that gets boring
alias lg='exa -lG'     # 'ls grid', exa is an interesting potential successor to 'ls', in Ubuntu 20.10 repo by default, colours each permission item and -lG is a useful 2x column long view.
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
    for d in /mnt/[a-z]; do [ -d /mnt/$(basename ${d}) ] && alias "$(basename ${d}):"="cd $d"; done         #  "d:" => cd to /mnt/d
    for d in /mnt/[a-z]; do [ -d /mnt/$(basename ${d}) ] && alias "l$(basename ${d}):"="cd $d && ll"; done   # "ld:" => cd to and list d:""
fi

答案1

反对使用的常见建议ls不是关于for循环,而是关于任何类型的输出解析ls。这包括几乎肯定会因奇怪的文件名而失败的事情ls | grep(例如,包含换行符或全局字符的文件名)。请仔细阅读https://mywiki.wooledge.org/ParsingLs为什么*不*解析`ls`(以及该怎么做)?

主要的一点是,您不想在循环或任何其他解析ls中使用的原因for与子目录无关,而与如何ls显示其结果有关。也就是说,有一个标志会导致ls(至少是 GNU ls,Linux 上的默认设置)不进入子目录:

       -d, --directory
              list directories themselves, not their contents

例如:

$ tree
.
├── dir1
│   ├── file1
│   ├── file2
│   └── file3
└── dir2
    ├── file1
    ├── file2
    └── file3

2 directories, 6 files

现在比较一下:

$ ls *
dir1:
file1  file2  file3

dir2:
file1  file2  file3

$ ls -d *
dir1  dir2

您已经在某些别名中使用了它。

至于lsdlsf别名,是的,正如你所说,这很笨拙,而且对于奇怪的文件名也会失败。仅列出目录的“标准”方式是:

ls -d */

我不知道如何仅获取 basic 的文件ls,如果您出于某种原因确实需要它,您可以使用find

find . -maxdepth 1 -type f

一般来说,ls它是为人类而不是脚本而设计的。因此,如果您需要解析它,总是有更好的工具。通常findstat.


其中一些别名根本不符合您的想法。这些,例如:

alias lx="ls -FlA | grep *"         # Executable files only, below 'lxext' is just trying to find 'executable-like' files by their extension
alias lnox="ls -FlA | grep -v *"    # Everything except executable files

由于别名会产生一个不带引号的*,因此 shell 在grep看到它之前就会对其进行扩展。因此,如果您有一个包含两个文件的目录:

$ ls
file1  file2

然后,lx将实际运行

ls  -FlA | grep file1 file2

因为*会扩展到目录的内容,所以file1 file2.结果是您的别名将完全忽略并使用 grep 查找文件中的ls字符串。这两个的可行替代方案是:file1file2

alias lx="find . -maxdepth 1 -executable -type f"
alias lnox="find . -maxdepth 1 -type f ! -executable"

浏览 28 个别名的列表远远超出了简单问答的范围,但这应该作为一个起点:忘记解析ls,它不能安全地完成,你应该使用别名与findorstat代替。

相关内容