提取文件名的一部分?

提取文件名的一部分?

我有一个以下形式的文件:

XXX XXXX XXX-6VwvOkZvzuI.description

我怎样才能只获取文件名XXX XXXX XXX?我试过了:

for file in $(ls .d*)
do
    fname="${file%*-}"
    ext="${filename%.*}"
done

答案1

不要解析ls(参见例如为什么*不*解析`ls`(以及该怎么做)?)。您遇到的问题是,您的循环变量 ,file将在文件名全部连接成一个长字符串后获取文件名的值,然后在空格上分割(以及在任何恰好是的分割词之后)通配模式已扩展)。您将获得 filename 循环的三次迭代XXX XXXX XXX-6VwvOkZvzuI.description,例如,值XXXXXXX和各循环一次XXX-6VwvOkZvzuI.description

迭代名称中包含破折号和.description使用的文件名后缀的所有文件

for name in *-*.description; do ...; done

-要挑选出in之前的部分$name,请使用标准参数扩展来删除-字符串中第一个之后的所有内容:

prefix=${name%%-*}

%%using和here之间的区别%在于,使用%%最长匹配的尾部字符串被删除。如果-任何名称中碰巧有多个字符,这一点很重要。

然后你的循环就变成了

for name in *-*.description; do
    prefix=${name%%-*}
done

文件名后缀已知 ( ),但您可以使用以下命令获取从 到后缀的.description文件名位-

infix=${name#"$prefix"}
infix=${infix%.description}

最后,使用类似的脚本

#!/bin/sh

suffix=.description

for name in *-*"$suffix"; do
    prefix=${name%%-*}
    infix=${name#"$prefix"}
    infix=${infix%.description}

    printf 'prefix="%s", infix="%s", suffix="%s"\n' \
        "$prefix" "$infix" "$suffix"
done

你会得到

$ ls
XXX XXXX XXX-6VwvOkZvzuI.description          XXX XXXX XXX-6VwvOkZvzuK.description
XXX XXXX XXX-6VwvOkZvzuJ.description          script
$ ./script
prefix="XXX XXXX XXX", infix="-6VwvOkZvzuI", suffix=".description"
prefix="XXX XXXX XXX", infix="-6VwvOkZvzuJ", suffix=".description"
prefix="XXX XXXX XXX", infix="-6VwvOkZvzuK", suffix=".description"

答案2

尝试这个

$ ls -1
x.sh
XXX XXXX XXX-6VwvOkZvzuI.description
YYY XXXX XXX-6VwvOkZvzuI.description
$ cat x.sh
#!/bin/bash
for file in *.d*
do
 fname=${file/-*/}
 ext=${file/*-/}
 echo fname $fname ext $ext
done
$ ./x.sh
fname XXX XXXX XXX ext 6VwvOkZvzuI.description
fname YYY XXXX XXX ext 6VwvOkZvzuI.description
$

答案3

编辑

我将保留我的答案,但添加 @Kusalananda 答案中的警告:不要解析ls(参见例如 为什么*不*解析`ls`(以及该怎么做)?)。

我的答案

您可以将 ls 的输出直接通过管道传输到 sed 中,并仅替换连字符 ( -) 之前的部分:

ls *.d* | sed 's/\(.*\)-.*/\1/'

我尝试使用两个名为的文件:

XXX XXXX XXX-6VwvOkZvzuI (copy).description
XXX XXXX XYZ-6VwvOkZvzuI.description

输出是:

XXX XXXX XXX
XXX XXXX XYZ

sed 命令的工作方式如下:

  • 我记得上面使用之间的内容\(\)在这种情况下,一切都取决于最后的文件名中的连字符(如果您的文件名称中包含后面的连字符,则需要对其进行调整)
  • 然后替换为记住的内容\1- 即仅 XXX 部分

如果需要,您可以将命令的输出放入文件中:

ls *.d* | sed 's/\(.*\)-.*/\1/' > new_file

相关内容