我有一个目录(包括子目录),我想找到所有扩展名为".ipynb"的文件。但是我希望'find'命令只返回这些文件名而不带扩展名。
我知道第一部分:
我知道第一部分:
find . -type f -iname "*.ipynb" -print
那么我如何获取没有“ipynb”扩展名的名称呢? 非常感谢您的回复...
尝试只返回没有扩展名的文件名:
find . -type f -iname "*.ipynb" -execdir sh -c 'printf "%s\n" "${0%.*}"' {} ';'
或(现在省略-type f
):
find "$PWD" -iname "*.ipynb" -execdir basename {} .ipynb ';'
find . -iname "*.ipynb" -exec basename {} .ipynb ';'
find . -iname "*.ipynb" | sed "s/.*\///; s/\.ipynb//"
不过,对每个文件都调用basename
可能会效率低下,因此@CharlesDuffy的建议是:
find . -iname '*.ipynb' -exec bash -c 'printf "%s\n" "${@%.*}"' _ {} +
find . -iname '*.ipynb' -execdir basename -s '.sh' {} +
使用 +
的意思是我们将多个文件传递给每个bash实例,因此如果整个列表适合单个命令行,则只调用一次bash。
要在同一行中打印完整路径和文件名(无扩展名),可以尝试:
find . -iname "*.ipynb" -exec sh -c 'printf "%s\n" "${0%.*}"' {} ';'
或:
find "$PWD" -iname "*.ipynb" -print | grep -o "[^\.]\+"
打印文件路径和文件名,分别显示在不同的行上:
find "$PWD" -iname "*.ipynb" -exec dirname "{}" ';' -exec basename "{}" .ipynb ';'
这里有一个简单的解决方案:
find . -type f -iname "*.ipynb" | sed 's/\.ipynb$//1'
for n in *.ipynb; do echo "${n%.ipynb}"; done
find . -type f -iname "*.ipynb" -exec sh -c 'f=$(basename $1 .ipynb);d=$(dirname $1);echo "$d/$f"' sh {} \;
f=$(basename "$1" .ipynb);d=$(dirname "$1"); echo "$d/$f"
-- 这样文件名中带有空格或通配符的情况就不容易出现问题。 - Charles Duffysh
副本,在其中生成子shell并运行非内置程序/bin/basename
,然后再生成另一个子shell调用/bin/dirname
。使用-exec ... {} +
可以让您在多个文件名之间共享单个sh
副本(尽管您需要迭代它们而不是硬编码$1
);更好的方法是将所有名称流式传输到执行工作的单个子进程中,根本不会启动任何新的每个名称子进程。 - Charles Duffybasename
的简单方法是:find . -type f -iname '*.ipynb' -exec basename -s '.ipynb' {} +
使用+
将减少命令的调用次数(manpage):
使用basename
和-s
选项可以接受多个文件名并删除指定的后缀(manpage):
-a, --multiple
支持多个参数,并将每个参数视为名称
-s, --suffix=SUFFIX
删除尾随的SUFFIX;意味着-a
Perl一行代码
你想要的内容
find . | perl -a -F/ -lne 'print $F[-1] if /.*.ipynb/g'
排除你不想要的代码
你不想要的内容
find . | perl -a -F/ -lne 'print $F[-1] if !/.*.ipynb/g'
注意
在 Perl 中,需要多加一个.
。所以您的模式应该是.*.ipynb
find . -type f -exec basename {} \;|perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'
并且返回一个没有重复文件的列表(最初在路径或扩展名上有所不同)
find . -type f -exec basename {} \;|perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'|sort|uniq
find . -type f -iname "*.ipynb" | grep -oP '.*(?=[.])'
-o标志仅输出匹配的部分。-P标志根据Perl正则表达式进行匹配。这是使lookahead (?=[.])
工作的必要条件。
tr
这种更简单的方法:find . -type f -iname "*.ipynb" -print | tr -d ".ipbyn"
tr
不关心字符是否有序,它将删除任何一个这些字符的所有出现。例如:echo snipsnap | tr -d ".ipbyn"
=> ssa
- stefansundin
basename
看起来相当低效。使用find . -name '*.ipynb' -exec bash -c 'printf "%s\n" "${@%.*}"' _ {} +
可以在每批文件中只调用一个 shell,因此开销要小得多。 - Charles Duffy+
表示我们将多个文件传递给每个 bash 实例 -- 如果整个列表适合单个命令行,则只调用一次 bash。 - Charles Duffy