Command-Line

使用普通家居用品設置兩個換行符終止列表的減法/通用黑名單

  • February 26, 2017

cp -r最近,當我在接收驅動器中用完空間時,我正在使用 備份目錄樹。我不得不繼續備份,但去另一個目的地。通常,要恢復cp命令,您會要求cp僅在文件不在目標位置時才複製文件。你可以在這裡看到問題。

這是我的解決方案:

  1. 搞砸。
# cp -rv sourcedir destdir
error: no space left on device.
  1. 列出所有已成功複製的文件。
# cd destdir
# find . >/tmp/alreadycopied
  1. 編寫一個腳本,它可以獲取任何列表 A 和一個黑名單 B,並返回一個新列表 C = B \ A,其中包含 A 中不在 B 中的所有元素。我稱之為 setminus。***generate list A*** | setminus listB將 C 返回到標準輸出。
  2. 使用 find 和 setminus 將所有剩余文件複製到新目標。
# cd sourcedir
# find . -type f | setminus /tmp/alreadycopied | xargs -d '\n' -I file cp -v --parents file overflowdestdir

它起作用了,但我認為這組減去列表是一個很常見的問題,標準 UNIX 工具必須以某種方式覆蓋這個案例,從而使我的腳本變得不必要。有沒有人遇到過這個問題,如果有,你是怎麼解決的?

setminus 腳本:

#!/usr/bin/env python3

# ***generate list*** | setminus blacklist
# Performs a set minus on its inputs and returns the result. Specifically,
# filters a newline-separated list in stdin using blacklist---also a
# newline-separated list. If an element of stdin is found in blacklist, it is
# excluded from the output. Otherwise, the element is returned to stdout. Very
# useful in conjunction with find commands.

from sys import *

try:
   blacklistfile = argv[1]
except IndexError:
   stderr.write('usage: ***generate list*** | setminus blacklist.\n')
   exit(1)

# A dict is used instead of a list to speed up searching. This blacklist could potentially be very large!
blacklist = {}
for line in open(blacklistfile):
   blacklist[line] = True

for line in stdin:
   inblacklist = False
   try:
       inblacklist = blacklist[line]
   except KeyError:
       pass

   if not inblacklist:
       stdout.write(line)

如果您的列表已排序,您可以使用它comm -23來獲取第一個列表的唯一元素。如果不是,您可以使用greplike

find -type f | grep -vFxf /tmp/alreadyCopied
  • -v將找到所有沒有匹配的行
  • -F告訴它使用字元串作為固定字元串,而不是模式
  • -x匹配整行而不是行中任意位置的字元串
  • -f /tmp/alreadyCopied從給定文件中讀取要匹配的行

不過,您必須確保路徑匹配,因此如果find正在生成./dir1/file1它需要是相同的字元串/tmp/alreadyCopied

但請注意,如果你有一個文件名,這種通用方法會出現問題\n。你可能可以find用類似的東西重做整個事情

find . -type f -exec test ! -f destdir/{} \; -exec cp -v --parents {} overflowdestdir \;

引用自:https://unix.stackexchange.com/questions/314713