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
文件名中的中间。
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)
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 的情况下,该技术通常很有用。
您只能使用 BASH 命令来执行此操作(无需任何外部工具)。
for file in *; do echo "${file%.*}"; done
Run Code Online (Sandbox Code Playgroud)
这在您没有 /usr/bin 时很有用,并且适用于像 this.is.image.png 这样的文件名和所有扩展名。
还不够吗?
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)
将删除所有扩展
ls
或管道[ 1 , 2 ]是不安全的find
解析(和管道)ls
or的输出是不安全的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)
在所有将在其中的情况下,通过管道将输出的ls
或find
下面的命令将没有任何提示,了解,如果本线来自于一个新的文件名,或者如果它遵循一个换行符的先例字符的文件名。确实是一个讨厌的名字,但仍然是一个合法的名字。
带有 shell Parameter-Expansion 的 shell 循环 , ${parameter%word}
,在带有printf
或的变体中都echo
可以工作[ cuonglm ], [ Anthon1 ]。
Run Code Online (Sandbox Code Playgroud)for f in *.png; do printf "%s\n" "${f%.png}" ; done
来自 Shell Parameter Expansion [ 3 ]的手册页
${parameter%word}
${parameter%%word}... 扩展的结果是删除了最短匹配模式('%' 大小写)或最长匹配模式('%%' 大小写)的参数值。