将文件移动到当前位置的父目录

Move files to parent directory of current location

我有很多文件夹,里面有一个文件夹,里面有文件。我想将第 2 级文件移动到第 1 级,并且不知道它们的名称。

简单示例:

我已经很接近了,但我遗漏了一些东西,我确定是 simple/stupid。这就是我 运行:

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

这就是我的灵感:

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

有什么建议吗?

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

但是,虽然它适用于一组文件夹,但如果我有更多文件夹,它就无法按预期工作。这就是我的意思:

之前:

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++ 中画画。你用的是什么?

mv YOUR-FILE-NAME ../

如果你有写权限,我应该这样工作

我用这个例子来说明:

树结构:

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/ 中的文件之后,那么您将从 temp 开始使用 -mindepth 3 访问它。请参阅:man find

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

  • ./: => 新建文件夹
  • ./*: => new/temp 文件夹
  • ./*/*: => new/temp/1stlevel

但所有这些都是针对 find 命令的,但另一个技巧是仅从 new 文件夹使用 mv 命令:

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

这是 运行 来自我示例中的新文件夹(换句话说,来自临时文件夹上方的一个文件夹)。对其进行不同级别的调整运行。

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

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

$ find . -mindepth 3 -type f -exec sh -c 'echo mv -i "" "${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%/*}/.."' 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%/*/*}"' 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

删除空的 SubFolder<i>N</i> 目录。 如果由于某种故障,它们中的任何一个都不为空, find 将保留它并发出警告消息。

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

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