我透過在終端機中使用以下命令列將一些檔案從來源資料夾複製到目標資料夾中。
sudo cp From_SOURCE/* To_DESTINATION/
現在我想撤銷這個命令。
答案1
如果我理解得好的話,情況如下:
- 您將大量(可能是大量)檔案複製到現有目錄,並且您需要/想要反轉該操作。
- 目標目錄包含一些其他文件,您需要保留在那裡,這使得不可能簡單地刪除全部目錄中的文件
下面的腳本查看原始(來源)目錄並列出這些檔案。然後,它會尋找將文件複製到的目錄,並僅刪除列出的文件,因為它們存在於來源目錄中。
新增該try
元素是為了防止錯誤,例如,如果您可能已經手動刪除了一些文件,或者並非來源目錄中的所有文件都複製到了目標。如果您需要 sudo 權限,只需使用「sudo」執行腳本即可(請參閱下文)。
劇本
#!/usr/bin/env python
import os
source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to
for root, dirs, files in os.walk(source_dir):
for name in files:
try:
os.remove(target_folder+"/"+name)
except FileNotFoundError:
pass
如何使用
- 將腳本貼到空文件中,另存為
reverse.py
, - 插入來源資料夾和目標資料夾的正確路徑,
- 出於方便原因使其可執行,
透過命令運行它:
[sudo] /path/to/reverse.py
警告
如果我很好地理解您需要實現的目標,請先嘗試測試目錄!
如果來源目錄是“平的”
如果來源目錄沒有子目錄,腳本甚至可以更簡單:
#!/usr/bin/env python
import os
source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to
for file in os.listdir(source_dir):
try:
os.remove(target_folder+"/"+file)
except FileNotFoundError:
pass
筆記
如果複製動作覆蓋(替換)目標中類似名稱的文件,該文件將被刪除,但原始文件(當然)不會被腳本帶回。假設不存在名稱衝突。
答案2
長話短說:
兩者中都存在的所有文件都src
可以dest
從中刪除,dest
如下所示:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
有關分步說明,請參閱下文。
簡化問題:
為了了解我們想要撤消的命令實際上做了什麼,我們首先對其進行簡化:
我們要撤銷的命令是
sudo cp From_SOURCE/* To_DESTINATION/
對於理解如何撤銷,sudo
並不相關。
src
我將使用和for 的From_SOURCE
目錄名稱。dest
To_DESTINATION
現在,我們的命令是:
cp src/* dest/
如果src
包含檔案f1
、f2
和f3
以及目錄d1
和d2
,則 shell 將該指令擴展為:
cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
-r
如果沒有、-R
或等選項-a
,則該指令cp
不會複製目錄。
這意味著,該命令會將它們排除在外,並顯示每個錯誤:
$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'
這意味著,我們僅將簡單文件複製到dest
.
決定要刪除哪些檔案:
可能存在dest
與 中的檔案同名的檔案src
。在這種情況下,文件被覆蓋 (1)。對他們來說已經太晚了,抱歉。從最新的備份中還原它們。
對於那裡的文件,我們只想刪除已複製的文件。這些檔案存在於兩個目錄中,具有相同的名稱和相同的內容。
所以我們尋找這些文件:
首先,我們cd
進入src
,因為它使下面的find
命令變得更加簡單,並將變數設為 dest 的絕對路徑:
$ cd src
$ destdir="$(readlink -f dest)"
然後,我們列出 src 中的所有檔案:
$ find . -maxdepth 1 -type f
並且,對於找到的每個文件,使用cmp
檢查 dest 中是否存在具有相同內容的文件:
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print
小心地刪除檔案:
這些文件是我們要刪除的文件。但可以肯定的是,我們首先將它們移動到不同的目錄中 - 並在運行它們之前查看命令:
$ toDelete=/tmp/toDelete ; mkdir -p "$toDelete"
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec echo mv -n "$destdir/{}" "$toDelete"/ \;
mv -n /path/to/dest/./f1 /tmp/toDelete/`
mv -n /path/to/dest/./f2 /tmp/toDelete/`
mv -n /path/to/dest/./f3 /tmp/toDelete/`
看起來不錯!現在我們可以省略echo
運行真正的mv
命令:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
其中的所有檔案dest
都是從 複製的,實際上在和src
中仍然相同,現在位於 中,並且可以在最後一次查看後刪除。src
dest
/tmp/toDelete/
注意:
(1) 檢查是否cp
為別名cp -i
,否則可以先詢問以防止覆蓋檔案。
答案3
這是舊的,但我只是想發布一個純粹的 bash 答案:
首先更改到複製檔案的目錄。
cd dest
然後,ls
來源目錄並將輸出透過管道傳輸到rm
ls source | xargs rm
答案4
這是基於複製操作的時間戳記的答案。您可以按建立時間順序列出資料夾內容並將其透過管道傳輸到檔案:
ls -alt | file_list
然後打開file_list
並找到與複製操作的時間戳相同的檔案。據推測,這些將是最新的文件。
然後編輯file_list
不需要rm -rf
的文件/資料夾並儲存。
然後做:
source file_list