'ls -1' :如何列出没有扩展名的文件名

Col*_*lin 35 ls shell grep

ls -1 像这样列出我的元素:

foo.png
bar.png
foobar.png
...
Run Code Online (Sandbox Code Playgroud)

我希望它没有.png像这样列出:

foo
bar
foobar
...
Run Code Online (Sandbox Code Playgroud)

(目录只包含.png文件)

有人可以告诉我grep在这种情况下如何使用吗?

目的:我有一个文本文件,其中列出了没有扩展名的所有名称。我想制作一个脚本,将文本文件与文件夹进行比较,以查看缺少哪个文件。

cas*_*cas 52

ls -1 | sed -e 's/\.png$//'
Run Code Online (Sandbox Code Playgroud)

sed命令删除(即用空字符串替换).png在文件名末尾找到的任何字符串。

.作为被转义\.,使得它被解释sed为一个文字.字符,而不是正则表达式.(其装置匹配任何字符)。该$是结束线的锚,所以它不匹配.png文件名中的中间。

  • 我认为 OP 想要删除 _any_ 扩展名,但可能只是“最后一个”。所以也许可以修改你的其他好答案:`sed 's/\.[^.]*$//'` (5认同)
  • `-1` 不是必需的,这里是默认值。 (4认同)
  • @jlliagre 我同意 cas 应该指定`-1`。这只是管道打开时的默认设置,这对某些人来说是一个隐藏的惊喜。因此,使其明确有助于理解。我也在我的脚本中这样做,所以我知道我期待什么样的输出。 (3认同)

cuo*_*glm 48

您只需要此工作的外壳。

POSIXly:

for f in *.png; do
    printf '%s\n' "${f%.png}"
done
Run Code Online (Sandbox Code Playgroud)

zsh

print -rl -- *.png(:r)
Run Code Online (Sandbox Code Playgroud)

  • @Conrad:在某些情况下,如果文件名以破折号开头或包含转义序列,则使用 echo 将无法正常工作。 (11认同)
  • 不需要`printf`;`echo ${f%.png}` 就足够了。 (4认同)
  • @DavidConrad:另见 http://unix.stackexchange.com/a/65819/38906 (3认同)
  • @DavidConrad 另外,我相信 printf 是内置的,就像 echo 一样,如果我错了,有人会纠正我 (2认同)

Ant*_*hon 19

如果您只想使用 bash:

for i in *; do echo "${i%.png}"; done
Run Code Online (Sandbox Code Playgroud)

您应该grep在尝试查找匹配项时使用,而不是删除/替换sed更合适的:

find . -maxdepth 1 -name "*.png"  | sed 's/\.png$//'
Run Code Online (Sandbox Code Playgroud)

一旦您决定需要创建一些子目录来为您的 PNG 文件添加顺序,您可以轻松地将其更改为:

find . -name "*.png"  | sed 's/\.png$//'
Run Code Online (Sandbox Code Playgroud)


hen*_*nnr 17

我会去basename(假设 GNU 实现):

basename --suffix=.png -- *.png
Run Code Online (Sandbox Code Playgroud)


Nor*_*ray 16

另一个非常相似的答案(我很惊讶这个特殊的变体还没有出现)是:

ls | sed -n 's/\.png$//p'
Run Code Online (Sandbox Code Playgroud)
  • 您不需要-1选项ls,因为ls假设标准输出不是终端(在这种情况下是管道)。
  • -n选项sed的意思是“默认不打印线”
  • /p替换末尾的选项表示“...如果进行了替换,则打印此行”。

这样做的净效果是只打印出以 结尾的那些行.png,并.png删除了。也就是说,这也迎合了 OP 问题的轻微概括,其中目录不只包含.png文件。

sed -n在您可能会使用 grep+sed 的情况下,该技术通常很有用。

  • @Hastur 原则上你是对的,关于 [don't parse ls](http://mywiki.wooledge.org/ParsingLs) 的著名页面列出了处理病理文件名时的进一步问题(和解决方案)。但是最好的处理方法是_避免使用病态的文件名_(doh!);如果你不能,或者如果你_必须_对它们很健壮,那么要么使用`find`,或者——可能更好——使用比`sh`更强大的语言来管理它们(`sh` _can_做所有事情的事实并不并不意味着它是每种情况下的最佳选择)。外壳首先是为可用性而设计的。 (2认同)

Luc*_*ini 9

您只能使用 BASH 命令来执行此操作(无需任何外部工具)。

for file in *; do echo "${file%.*}"; done 
Run Code Online (Sandbox Code Playgroud)

这在您没有 /usr/bin 时很有用,并且适用于像 this.is.image.png 这样的文件名和所有扩展名。


Roh*_*bas 7

还不够吗?

ls -1 | sed 's/\.png//g'
Run Code Online (Sandbox Code Playgroud)

或者一般来说,这

ls -1 | sed 's/\.[a-z]*//g'
Run Code Online (Sandbox Code Playgroud)

将删除所有扩展


Has*_*tur 7

解析ls或管道[ 1 , 2 ]是不安全的find

解析(和管道)lsor的输出是不安全的find,主要是因为可以在文件名中找到非常用字符作为换行符制表符......这里纯 shell 循环将起作用[ cuonglm ]
即使没有通过管道传递选项的find命令-exec能工作:

find ./*.png  -exec  basename {} .png  \;
Run Code Online (Sandbox Code Playgroud)

更新/注释:您find .甚至可以使用搜索隐藏文件,或find ./*.png仅获取未隐藏的文件。有了find *.png -exec ...你可以在案件问题是当前一个文件名为.png因为发现会得到它作为一个选项。您可以添加-maxdepth 0以避免在名为 as 的目录中下降Dir_01.png,或者find ./*.png -prune -exec ...在不允许使用 maxdepth 时(感谢 Stéphane)。如果您想避免列出这些目录,您应该添加该选项-type f(这也将排除其他类型的非常规文件)。查看man有关所有可用选项的更完整全景图,并记住检查它们何时符合 POSIX,以获得更好的可移植性。

多说几句

例如,可能会发生从文档中复制标题并粘贴到文件名中的情况,一个或多个换行符将在文件名本身中完成。我们甚至可能很不幸,标题甚至可以包含我们必须在换行符之前使用的键:

The new art of working on .png
files and other formats.
Run Code Online (Sandbox Code Playgroud)

如果要测试,可以使用命令创建这样的文件名

touch "A file with two lines"$'\n'"and This is the second.png"
touch "The new art of working on .png"$'\n'"files and other formats.png"
Run Code Online (Sandbox Code Playgroud)

简单的/bin/ls *png将输出?而不是不可打印的字符

A file with two lines?and This is the second.png
The new art of working on .png?files and other formats.png
Run Code Online (Sandbox Code Playgroud)

在所有将在其中的情况下,通过管道将输出lsfind下面的命令将没有任何提示,了解,如果本线来自于一个新的文件名,或者如果它遵循一个换行符的先例字符的文件名。确实是一个讨厌的名字,但仍然是一个合法的名字。

带有 shell Parameter-Expansion 的 shell 循环 , ${parameter%word},在带有printf或的变体中都echo可以工作[ cuonglm ], [ Anthon1 ]

for f in *.png; do printf "%s\n" "${f%.png}" ; done
Run Code Online (Sandbox Code Playgroud)

来自 Shell Parameter Expansion [ 3 ]的手册页

${parameter%word}
${parameter%%word}

... 扩展的结果是删除了最短匹配模式('%' 大小写)或最长匹配模式('%%' 大小写)的参数值。