将文件移动到当前位置

时间:2018-04-22 16:50:39

标签: linux shell mv

我有很多文件夹里面有一个文件夹,里面有文件。我想将第二级文件移动到第一级,并且在不知道其名称的情况下这样做。

简单示例:

  • 在运行脚本之前:

    /temp/1stlevel/test.txt
    /temp/1stlevel/2ndlevel/test.rtf
    
  • 运行脚本后:

    /temp/1stlevel/test.txt
    /temp/1stlevel/test.rtf
    

我变得非常接近,但我错过了一些东西,我确信它很简单/愚蠢。这就是我正在运行的:

find . -mindepth 3 -type f -exec sh -c 'mv -i "$1" "${1%/*}"' sh {} \;

这就是我的意思:

mv: './1stlevel/2ndlevel/test.rtf' and './1stlevel/2ndlevel/test.rtf' are the same file

有什么建议吗?

更新:乔治,这很棒,谢谢!我正在学习很多并做笔记。使用mv命令而不是更复杂的命令是很棒的。远非我第一次被指责以最艰难的方式做事!

然而,虽然它适用于1套文件夹,但如果我有更多,它不会按预期工作。这就是我的意思:

在:

new
└── temp
    ├── Folder1
    │   ├── SubFolder1
    │   │   └── SubTest1.txt
    │   └── Test1.txt
    ├── Folder2
    │   ├── SubFolder2
    │   │   └── SubTest2.txt
    │   └── Test2.txt
    └── Folder3
        ├── SubFolder3
        │   └── SubTest3.txt
        └── Test3.txt

后:

new
└── temp
    └── Folder3
        ├── Folder1
        │   ├── SubFolder1
        │   └── Test1.txt
        ├── Folder2
        │   ├── SubFolder2
        │   └── Test2.txt
        ├── SubFolder3
        ├── SubTest1.txt
        ├── SubTest2.txt
        ├── SubTest3.txt
        └── Test3.txt

所需:

new
└── temp
    ├── Folder1
    │   ├── SubFolder1
    │   ├── SubTest1.txt
    │   └── Test1.txt
    ├── Folder2
    │   ├── SubFolder2
    │   ├── SubTest2.txt
    │   └── Test2.txt
    └── Folder3
        ├── SubFolder3
        ├── SubTest3.txt
        └── Test3.txt

如果有人想得到幻想*:

new
└── temp
    ├── Folder1
    │   ├── SubTest1.txt
    │   └── Test1.txt
    ├── Folder2
    │   ├── SubTest2.txt
    │   └── Test2.txt
    └── Folder3
        ├── SubTest3.txt
        └── Test3.txt
  • 我不需要花哨,但是,因为我的脚本稍后会删除空文件夹。
顺便说一下,这让我在Notepad ++中永远画画。你用了什么?

4 个答案:

答案 0 :(得分:3)

您的find . -mindepth 3 -type f -exec sh -c 'mv -i "$1" "${1%/*}"' sh {} \; 尝试非常接近正确。 调试复杂命令时的一种有用技巧 是插入echo语句来查看发生的情况。 所以,如果我们说

$ find . -mindepth 3 -type f -exec sh -c 'echo mv -i "$1" "${1%/*}"' sh {} \;
,我们会得到

mv -i ./Folder1/SubFolder1/SubTest1.txt ./Folder1/SubFolder1
mv -i ./Folder2/SubFolder2/SubTest2.txt ./Folder2/SubFolder2
mv -i ./Folder3/SubFolder3/SubTest3.txt ./Folder3/SubFolder3

这非常有意义 - 它正在查找深度为3(及以上)的所有文件, 从路径名中删除最后一级,然后将文件移到那里。 但是,

mv  (path_to_file)  (path_to_directory) 
手段 将文件移动到目录中 所以命令mv -i ./Folder1/SubFolder1/SubTest1.txt ./Folder1/SubFolder1 表示将Folder1/SubFolder1/SubTest1.txt 移至 Folder1/SubFolder1 - 但那就是它已经存在的地方。 因此,您收到错误消息说 您正在将文件移动到已经存在的位置。

从你的插图中可以清楚地看到, 您想将SubTest1.txt移至Folder1。 一个快速解决方法是

$ find . -mindepth 3 -type f -exec sh -c 'mv -i "$1" "${1%/*}/.."' sh {} \;

使用..SubFolder1升级到Folder1

mv -i ./Folder1/SubFolder1/SubTest1.txt ./Folder1/SubFolder1/..
mv -i ./Folder2/SubFolder2/SubTest2.txt ./Folder2/SubFolder2/..
mv -i ./Folder3/SubFolder3/SubTest3.txt ./Folder3/SubFolder3/..

我相信那是不好的风格,虽然我无法弄明白为什么。 我更喜欢

$ find . -mindepth 3 -type f -exec sh -c 'mv -i "$1" "${1%/*/*}"' sh {} \;

使用%/*/*从文件的路径名中删除两个组件 得到你真正想要的东西,

mv -i ./Folder1/SubFolder1/SubTest1.txt ./Folder1
mv -i ./Folder2/SubFolder2/SubTest2.txt ./Folder2
mv -i ./Folder3/SubFolder3/SubTest3.txt ./Folder3

然后您可以使用

$ find . -mindepth 2 -type d –delete

删除空的SubFolderN目录。 如果由于某些故障,其中任何一个都不是空的, find将不理会并发出警告信息。

答案 1 :(得分:2)

让我用这个例子来说明:

树形结构:

new
└── temp
    └── 1stlevel
        ├── 2ndlevel
        │   └── text.rtf
        └── test.txt

移动:

find . -mindepth 4 -type f -exec mv {} ./*/* \; 

搬家后的结果:

new
└── temp
    └── 1stlevel
        ├── 2ndlevel
        ├── test.txt
        └── text.rtf

如果您从问题运行它,我从temp文件夹中的一个文件夹运行,如果您想从temp文件夹运行它,那么命令将是:

find 1stlevel/ -mindepth 2 -type f -exec mv {} ./* \;

或者:

find ./ -mindepth 3 -type f -exec mv {} ./* \;

请仔细查看find ./ -mindepth 3部分,记住-mindepth 1 means process all files except the starting-points。因此,如果您从temp开始并且在temp/1st/2nd/中的文件之后,那么您将使用-mindepth 3从temp开始访问它。请参阅:man find

现在,对于我使用./*/*的目的地,解释“从当前(一个从temp,我的是新的)目录下降到temp,然后1stlevel,所以:

  • ./:=>新文件夹
  • ./*:=> new / temp文件夹
  • ./*/*:=>新的/温度/ 1stlevel

但是find命令的所有内容,但另一个技巧是仅使用mv文件夹中的new命令:

mv ./*/*/*/* ./*/*

这是从我的示例中的新文件夹运行的(换句话说,从temp文件夹中的一个文件夹)。进行调整以在不同级别运行它。

temp文件夹中运行:

mv ./*/*/* ./*

如果你提到你有很多文件,那么你的时间已经接近了,那么mv选项会胜过find选项。只查看三个文件的时间结果:

查找

real    0m0.004s
user    0m0.000s
sys     0m0.000s

MV:

real    0m0.001s
user    0m0.000s
sys     0m0.000s

更新

由于OP想要一个脚本来访问我带来的多个文件夹:

  
#!/usr/bin/env bash

for i in ./*/*/*;
do
        if [[ -d "$i" ]];
        then
                # Move the files to the new location
                mv "$i"/* "${i%/*}/"
                # Remove the empty directories
                rm -rf "$i"

        fi
done

如何:从新文件夹:./move.sh运行,请记住使用chmod +x move.sh使脚本可执行。

目标目录结构:

new
├── move.sh
└── temp
    ├── folder1
    │   ├── subfolder1
    │   │   └── subtext1.txt
    │   └── test1.txt
    ├── folder2
    │   ├── subfolder2
    │   │   └── subtext2.txt
    │   └── test1.txt
    └── folder3
        ├── subfolder3
        │   └── subtext3.txt
        └── test1.txt

获得花哨的结果:

new
├── move.sh
└── temp
    ├── folder1
    │   ├── subtext1.txt
    │   └── text1.txt
    ├── folder2
    │   ├── subtext2.txt
    │   └── text2.txt
    └── folder3
        ├── subtext3.txt
        └── text3.txt

答案 2 :(得分:0)

for( $i=0; $i<=10; $i++ )
{ 
    if( $i%2 == 0 ){
        echo $i;
    }
}
如果你有写作权限,我会以这种方式工作

答案 3 :(得分:0)

让您的脚本导航到您需要移动文件的每个目录&#34; up,&#34;然后你可以find找到目录中的每个文件,然后将它们移到一个目录中:

 $ find . -type f -exec mv {} ../. \;