رسينك --حذف --ملفات=قائمة / دست/ لا حذف الملفات غير المرغوب فيها
-
06-07-2019 - |
سؤال
كما ترون في العنوان أنا في محاولة مزامنة مجلد مع قائمة من الملفات.تمنيت أن هذا الأمر من شأنه أن حذف كافة الملفات في دست/ التي ليست في القائمة ، لكنه لم يفعل.
لذا بحثت قليلا و نعرف الآن أن رسينك لا يمكن أن تفعل هذا.
ولكن أنا في حاجة إليها ، لذلك هل تعرف أي طريقة للقيام بذلك ؟
PS:القائمة التي تم إنشاؤها بواسطة البرنامج النصي الثعبان ، لذلك لا يمكن تصورها أن الحل الخاص بك يستخدم بعض كود بايثون.
تحرير, دعونا نكون الخرسانة:
قائمة تبدو مثل هذا:
/home/max/Musik/Coldplay/Parachutes/Trouble.mp3
/home/max/Musik/Coldplay/Parachutes/Yellow.mp3
/home/max/Musik/Coldplay/A Rush of Blood to the Head/Warning Sign.mp3
/home/max/Musik/Coldplay/A Rush of B-Sides to Your Head/Help Is Around the Corner.mp3
/home/max/Musik/Coldplay/B-Sides (disc 3)/Bigger Stronger.mp3
و الأمر من هذا القبيل:
rsync --delete --files-from=/tmp/list / /home/max/Desktop/foobar/
يعمل هذا, ولكن إذا قمت بحذف الخط لا يتم حذف في foobar/.
تحرير 2:
rsync -r --include-from=/tmp/list --exclude=* --delete-excluded / /home/max/Desktop/foobar/
الذي يعمل لا ...
المحلول
ربما يمكنك القيام بذلك باستخدام قائمة تشمل أنماط بدلا من استخدام --delete-excluded
(الذي لا كما يوحي الاسم)?شيء من هذا القبيل:
rsync -r --include-from=<patternlistfile> --exclude=* --delete-excluded / dest/
إذا أسماء الملفات من المرجح أن تحتوي على أحرف البدل (*
, ?
و [
) ثم قد تحتاج إلى تعديل الثعبان إلى الهروب منها:
re.sub("([[*?])", r"\\\1", "abc[def*ghi?klm")
تحرير: القائمة على نمط مطابقة يعمل بشكل مختلف قليلا --files-from
في هذا rsync
لن recurse إلى الدلائل التي تتطابق مع استبعاد نمط لأسباب من الكفاءة.حتى إذا كان لديك ملفات في /some/dir
و /some/other/dir
ثم نمط الملف يحتاج إلى تبدو مثل:
/some/
/some/dir/
/some/dir/file1
/some/dir/file2
/some/other/
/some/other/dir/
/some/other/dir/file3
...
بدلا من ذلك, إذا كانت جميع الملفات في نفس الدليل حيث يمكنك كتابة الأمر قليلا:
rsync -r --include-from=<patternlistfile> --exclude=* --delete-excluded /some/dir/ dest/
ثم أنماط الخاص بك تصبح:
/file1
/file2
تحرير: التفكير حول هذا الموضوع ، يمكن أن تشمل جميع الدلائل مع نمط واحد:
/**/
ولكن بعد ذلك كنت في نهاية المطاف مع الدليل بالكامل شجرة في dest/
والتي ربما ليس ما تريد.ولكن الجمع بين ذلك مع -m
(الذي الخوخ الدلائل الفارغة) يجب حل هذا - لذا فإن الأمر ينتهي شيئا مثل:
rsync -m -r --delete-excluded --include-from=<patternfile> --exclude=* / dest/
و نمط الملف:
/**/
/some/dir/file1
/some/other/dir/file3
نصائح أخرى
وهذا ليس بالضبط الحل، ولكن الناس يأتون إلى هنا قد تجد هذه المفيد: منذ رسينك 3.1.0 هناك معلمة --delete-missing-args
الذي حذف الملفات في الدليل الوجهة عند مزامنة دليلين باستخدام --files-from
. سوف تحتاج إلى تحديد الملفات المحذوفة في /tmp/list
جنبا إلى جنب مع الملفات التي لا تريد نسخها:
rsync --delete-missing-args --files-from=/tmp/list /source/dir /destination/dir
الصفحة رجل للحصول على مزيد من التفاصيل.
وكما أوضح، الأمر
rsync -r --delete --files-from=$FILELIST user@server:/ $DEST/
لا تقم بحذف المحتوى في الوجهة عندما تمت إزالة إدخال من $ FILELIST. وهناك حل بسيط هو استخدام بدلا من ذلك ما يلي:
mkdir -p $DEST
rm -rf $TEMP
rsync -r --link-dest=$DEST --files-from=$FILELIST user@server:/ $TEMP/
rm -r $DEST
mv $TEMP $DEST
وهذا يرشد رسينك لاستخدام وجهة فارغة. الملفات الموجودة في الارتباط دست-الدليل بالفعل هي محليا ترتبط بجد وليس نسخها. وأخيرا يتم استبدال الوجهة القديمة واحدة جديدة. ومكدير الأول يخلق $ DEST فارغا إذا $ DEST لا وجود لها، لمنع الخطأ رسينك. (ويفترض أن -variables $ لتنفيذ المسار الكامل للملف المعني أو الدليل).
وهناك بعض النفقات العامة طفيف ل-ربط الصلب، ولكنك لا تحتاج إلى فوضى مع مجمع وتشمل / استبعاد استراتيجيات.
ومستوحاة من m4t، ولكن باستخدام ... رسينك لتنظيف
rsync -r --link-dest=$dst --files-from=filelist.txt user@server:$source/ $temp
rsync -ra --delete --link-dest=$temp $temp/ $dest
وصريحة بناء --exclude-من = ... يبدو أن الطريقة الوحيدة لقائمة الملفات مزامنة.
stdin = subprocess.PIPE
other_params.append("--exclude-from=-") #from stdin
p = subprocess.Popen( 'rsync -e ssh -zthvcr --compress-level=9 --delete'.split() + other_params + [src, dst], stdin = PIPE)
if relative_files_list != None:
#hack: listing of excluded files seems the only way to delete unwanted files at destination
files = set(map(norm_fn, relative_files_list)) #make hash table, for huge lists
for path, ds, fs in os.walk(src):
for f in fs:
rel_path_f = norm_fn(os.path.relpath(os.path.join(path, f), src))
if rel_path_f not in files:
#print 'excluding', rel_path_f.replace('\\', '/')
p.stdin.write(rel_path_f + '\n')
p.stdin.close()
assert 0 == p.wait()
وأنا أدرك سئل هذا السؤال قبل فترة طويلة، لكنني كنت غير راض عن الإجابة.
وهنا هو كيف تحل المشكلة، على افتراض قائمة التشغيل التي أنشأتها mpd
:
#!/bin/bash
playlist_path="/home/cpbills/.config/mpd/playlists"
playlist="${playlist_path}/${1}.m3u"
music_src="/home/cpbills/files/music"
music_dst="/mnt/sdcard/music/"
if [[ -e "$playlist" ]]; then
# Remove old files
find "$music_dst" -type f | while read file; do
name="$(echo "$file" | sed -e "s!^$music_dst!!")"
if ! grep -qF "$name" "$playlist"; then
rm "$file"
fi
done
# Remove empty directories
find "$music_dst" -type d -exec rmdir {} \; 2>/dev/null
rsync -vu \
--inplace \
--files-from="$playlist" \
"$music_src" "$music_dst"
else
printf "%s does not exist\n" "$playlist" 1>&2
exit 1
fi
رسينك مثالية لحفظ الدلائل في المزامنة ، من بين أشياء أخرى مفيدة.إذا كان لديك نسخة طبق الأصل عن المصدر ، و تريد حذف الملفات على دست يمكنك حذفها من المصدر rsync --delete
خيار حذفها من دست أيضا.
ومع ذلك, إذا لديك فقط التعسفي قائمة الملفات التي تريد حذفها ، أقترح عليك استخدام SSH لتحقيق ذلك:
ssh user@remote.host.com rm /path/to/file1 /path/to/file2
هذا سيتم تنفيذ rm
القيادة على المضيف البعيد.
باستخدام بيثون, يمكنك:
import subprocess
FileList = ['/path/to/file1', '/path/to/file2']
subprocess.call(['ssh', 'dAnjou@my.server.com', 'rm'] + FileList)
~الاستمتاع