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

Yor*_*ubs 2 ls bash

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来运行裸命令,忽略别名。

向条目 vs附加-F一个指示符(其中之一*/=>@|color=alwayscolor=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}"   /sf/ask/546862711/
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
Run Code Online (Sandbox Code Playgroud)

ter*_*don 12

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

\n

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

\n
       -d, --directory\n              list directories themselves, not their contents\n
Run Code Online (Sandbox Code Playgroud)\n

例如:

\n
$ tree\n.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dir1\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file1\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file2\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file3\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 dir2\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file1\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file2\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file3\n\n2 directories, 6 files\n
Run Code Online (Sandbox Code Playgroud)\n

现在比较一下:

\n
$ ls *\ndir1:\nfile1  file2  file3\n\ndir2:\nfile1  file2  file3\n
Run Code Online (Sandbox Code Playgroud)\n

\n
$ ls -d *\ndir1  dir2\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

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

\n
ls -d */\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
find . -maxdepth 1 -type f\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

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

\n
alias lx="ls -FlA | grep *"         # Executable files only, below \'lxext\' is just trying to find \'executable-like\' files by their extension\nalias lnox="ls -FlA | grep -v *"    # Everything except executable files\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
$ ls\nfile1  file2\n
Run Code Online (Sandbox Code Playgroud)\n

然后,lx将实际运行

\n
ls  -FlA | grep file1 file2\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
alias lx="find . -maxdepth 1 -executable -type f"\nalias lnox="find . -maxdepth 1 -type f ! -executable"\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n