bash使用文件的basename创建dir,然后将相应的移动到

时间:2014-01-12 18:31:49

标签: bash for-loop

所以我有点容易的问题: 我有成千上万的文件具有相同的基本名称,但有不同的扩展名(多个)。例如,我有以下内容:

t_2dri.manual.ali_porter.inseq  
t_2dri.manual.ali_porter.inseq.porter   

t_2dri.tm.ali_porter.inseq 
t_2dri.tm.ali_porter.inseq.porter       

t_3ezm.manual.ali_porter.inseq  
t_3ezm.manual.ali_porter.inseq.porter

t_8gep.fast.ali_porter.inseq 
t_8gep.fast.ali_porter.inseq.porter        

我想得到的是直率:

t_2dri.manual.ali
t_2dri.tm.ali
t_3ezm.manual.ali
t_8gep.fast.ali

我用以下脚本执行此操作:

for i in *.porter;do
    bn=$(basename $i _porter.inseq.porter)
    mkdir $bn;done

哪个有效(也许我可以做得更好/更短)?

第二个问题是如何将文件放入正确的文件夹中 - 我尝试了几个脚本和for循环,但还没有成功。


好的,所以我得到了我需要的答案的一半,但其中一些确实是错误的,现在为了让我们(我:)更容易理解:

我有名为

的文件夹
folder1.sth
folder2.sth
folder3.sth

并且在同一目录中我有以下文件:

   folder1.sth.sth.blah
   folder3.sth.other.thing 
   folder1.sth.any.other.thing

如何将 .sth。的每个文件放入相应的* .sth文件夹(具有相同的前缀)


好的,晚餐后的星期日是本周的宇宙时间

对我有用的东西(虽然我可以在半小时前拍到它)是:

for i in *.sth;do
    mv $i.* $i;
    done

好的,所以我做错了就是

for i in *.ali;do
  2     mv $i_* $i;
  3     done

不同
for i in *.ali;do
  2     mv $i.* $i;
  3     done

在$ i。*的方式是$ i它有的东西。之后和之后的东西,而$ i_意味着完全不同的东西 - 不知道还有什么以及如何省略它,也许有人会帮忙?

3 个答案:

答案 0 :(得分:1)

for base in t_2dri.manual.ali t_2dri.tm.ali t_3ezm.manual.ali t_8gep.fast.ali; do
    mkdir $base
    mv "${base}*" $base/
done

如果因为有数以万计的文件而出现argument list too long错误,您只需循环遍历它们,因此:

for base in t_2dri.manual.ali t_2dri.tm.ali t_3ezm.manual.ali t_8gep.fast.ali; do
    mkdir $base
    for file in ${base}*; do
        mv "$file" $base/
    done
done

答案 1 :(得分:1)

我在这里回答了一个非常相似的问题Move a group of files to a new folder if their file names, minus extension, matches?下面的细微变化应该适用于你想要的东西。

要获得这种情况下的文件名,您可以在bash中使用它

"${i%%.ali*}.ali" #This will match the longest possible match of ".ali*" in the string and remove it, leaving everything before it, and then we append ".ali" back to the end.

因此,将脚本从另一个答案修改为您想要的内容:

#!/bin/bash

dir="/somedir/"
for i in "$dir"*; do
  if [[ -f $i && $i == *".ali"* ]]; then
    filename="${i%%.ali*}.ali"
    if [ ! -d "$filename" ]; then
      mkdir "$filename"
    fi

    mv "$i" "$filename"
  fi

done

作出解释。将您想要完成的目录放在dir="/somedir/"中。然后,它将遍历该目录中的所有文件(常规文件,目录,符号链接等)。然后它检查给定文件是否是包含 ali 的常规文件。如果是,则检查具有给定文件名的目录是否存在.ali,如果它不存在,则将文件移动到相关目录。

如果/somedir/包含您列出的文件,则会生成

|-- t_2dri.manual.ali
|   |-- t_2dri.manual.ali_porter.inseq
|   `-- t_2dri.manual.ali_porter.inseq.porter
|-- t_2dri.tm.ali
|   |-- t_2dri.tm.ali_porter.inseq
|   `-- t_2dri.tm.ali_porter.inseq.porter
|-- t_3ezm.manual.ali
|   |-- t_3ezm.manual.ali_porter.inseq
|   `-- t_3ezm.manual.ali_porter.inseq.porter
`-- t_8gep.fast.ali
    |-- t_8gep.fast.ali_porter.inseq
    `-- t_8gep.fast.ali_porter.inseq.porter

更新已修改问题的解决方案

#!/bin/bash
for i in *".sth"*; do
  [ -f "$i" ] &&  mv "$i" "${i%%.sth*}.sth/"
done

答案 2 :(得分:0)

cat INPUT.txt | while read FILE ; do
    ## skip blank lines & non-existing files in INPUT.txt
    if [[ $FILE == "" ]] | [[ ! -f $FILE ]] ; then
        continue
    fi

    ## set $BN as dir name
    BN=$(basename $FILE| sed 's/\(.*\)_porter.*/\1/')

    ## make dir if dir does not exist
    if [[ ! -d $BN ]] ; then
        mkdir $BN
    fi

    ## move file to inside dir
    mv $FILE $BN
done

假设:

  • INPUT.txt 是输入文件&它包含现有文件的完整路径
    (如果找不到文件,则跳过操作)

  • 除非您更改$BN变量中的内容,否则将在当前工作目录中创建目录(即您运行脚本的位置)