Fayllarni topishda foydalanib, katalog tuzilishini saqlang

Manba katalogidan maqsad katalogiga belgilangan eski kun fayllarini ko'chirishga yordam beradigan quyidagi buyruqni yaratdim. U mukammal ishlaydi.

#!/bin/bash

echo "Enter Your Source Directory"
read soure

echo "Enter Your Destination Directory"
read destination 

echo "Enter Days"
read days



 find "$soure" -type f -mtime "-$days" -exec mv {} "$destination" \;

  echo "Files which were $days Days old moved from $soure to $destination"

Ushbu skriptlar fayllarni katta ko'chiradi, shuningdek, manba pastki katalog fayllarini ko'chiradi, lekin u maqsad katalogga kichik katalog yaratmaydi. Men bu qo'shimcha funktsiyani amalga oshirishni xohlayman.

misol bilan

/home/ketan     : source directory

/home/ketan/hex : source subdirectory

/home/maxi      : destination directory

Ushbu skriptni ishga tushirganimda, u hex fayllarini maksimal katalogga ko'chiradi, lekin shunga o'xshash hex maksimal katalogga aylantirilishi va fayllarni bir xil hex ichida ko'chirish kerak.

20

9 javoblar

find kodini bilaman, lekin bu rsync uchun ish kabi ko'rinadi.

Men ko'pincha quyidagilarni foydalanaman:

rsync -axuv --delete-after --progress Source/ Target/

Agar siz ma'lum bir fayl turini (faqatgina "https://silentorbit.com/notes/2013/08/rsync-by-extension/" rel = "noreferrer" fayllarini ko'chirishni istasangiz) > Bu yerdan ):

rsync -rv --include '*/' --include '*.js' --exclude '*' --prune-empty-dirs Source/ Target/
10
qo'shib qo'ydi
boshqa echimlardan ancha toza :)
qo'shib qo'ydi muallif Kaz, manba
- remove-source-files faylini foydali deb topdim, natijada fayllar nusxalash o'rniga ko'chiriladi. Ushbu rsyncning ajoyib usuli.
qo'shib qo'ydi muallif Tom, manba

mv/home/ketan/hex/foo/home/maxi ni ishlatish o'rniga, find tomonidan ishlab chiqarilgan yo'lga qarab maqsadli katalogni o'zgartiring. Agar siz avval manba katalogiga o'zgartirsangiz va toping. ni ishlatsangiz, bu osonroq. Endi find tomonidan ishlab chiqarilgan har bir elementga maqsad katalogni kiritishingiz mumkin. Birlashtirishni amalga oshirish va agar kerak bo'lsa, maqsadli katalog yaratish uchun find ... -exec buyrug'ida qobiqni ishlatish kerak.

destination=$(cd -- "$destination" && pwd) # make it an absolute path
cd -- "$source" &&
find . -type f -mtime "-$days" -exec sh -c '
  mkdir -p "$0/${1%/*}"
  mv "$1" "$0/$1"
' "$destination" {} \;

Eslatma: $ destination maxsus belgilarni o'z ichiga olgan holda quoting masalalaridan qochish uchun uni faqat shell skriptida o'zgartirishingiz mumkin emas. Uni ichki qobiqga yetkazishi uchun uni atrof muhitga eksport qilishingiz mumkin yoki uni argument sifatida qabul qilishingiz mumkin (men qilgan narsam). sh guruhini guruhlash orqali biroz ijro qilish vaqtini saqlashingiz mumkin:

destination=$(cd -- "$destination" && pwd) # make it an absolute path
cd -- "$source" &&
find . -type f -mtime "-$days" -exec sh -c '
  for x do
    mkdir -p "$0/${x%/*}"
    mv "$x" "$0/$x"
  done
' "$destination" {} +

Shu bilan bir qatorda, zsh da zmv code> funktsiyasi va . va m glob saralashlari faqat to'g'ri sana oralig'idagi muntazam fayllar bilan mos kelishiga ishonch hosil qilish uchun. Agar zarurat bo'lsa, avval maqsadli katalogni yaratadigan muqobil mv funksiyasidan o'tishingiz kerak.

autoload -U zmv
mkdir_mv() {
  mkdir -p -- $3:h
  mv -- $2 $3
}
zmv -Qw -p mkdir_mv $source/'**/*(.m-'$days')' '$destination/$1$2'
9
qo'shib qo'ydi
@ MichałGórny uchun for x; texnik jihatdan POSIX-mos emas ( grammatikasiga ), lekin zamonaviy kabuklar x uchun ikkala kodni bajarish uchun ruxsat beradi va x uchun ; bajaring ; ba'zi bir sobiq Bourne kabukları x uchun ni tushirmadi; -ni tanlang. sh -c '...' arg0 arg1 arg2 arg3 bilan ishlaydigan zamonaviy kabuklarda arg0 kodi $ 0 bo'lib, arg1 $ 1 va boshqalar. Agar $ 0 sh bo'lishini xohlasangiz, sh -c '...' sh yozing. arg1 arg2 arg3 . Shunga qaramay, ba'zi Bourne kabukları boshqacha yo'l tutdi, lekin buni POSIX »bildiradi.
qo'shib qo'ydi muallif Valters Vingolds, manba
for x do uchun ; kodi mavjud :). Bundan tashqari, $ 0 bilan nima qilishni xohlayotganingizni bilmayman, lekin sh bo'lishi mumkinligiga ishonchim komil.
qo'shib qo'ydi muallif JSolano, manba
pushd cd , hozirgi zamonga nisbatan zo'ravonlik qiladigan eng yaxshi variantga o'xshaydi.
qo'shib qo'ydi muallif jpmc26, manba

Bu juda samarali emas, lekin kodni o'qish va tushunish osonroq, faqatgina fayllarni nusxalash va so'ngra o'chirib tashlashingiz mumkin.

find /original/file/path/* -mtime +7 -exec cp {} /new/file/path/ \;
find /original/file/path/* -mtime +7 -exec rm -rf {} \;

Eslatma: Avtomatik operatsiyalar uchun @MV tomonidan aniqlangan nuqson:

Ikki alohida amaliyotdan foydalanish talabga javob. Agar ba'zi fayllar 7 kundan katta bo'lsa   replikatsiya jarayoni amalga oshirilsa, ular ko'chirilmaydi, ammo o'chiriladi   o'chirish jarayoni. Agar bunday bo'lmasa, qo'l bilan bajariladigan narsa uchun   bir muammo, ammo avtomatlashtirilgan skriptlar uchun bu ma'lumotlar yo'qolishiga olib kelishi mumkin.

3
qo'shib qo'ydi
Ikki alohida operatsiyadan foydalanish xavfli. Nusxalash jarayoni amalga oshirilayotganda ayrim fayllar 7 kundan katta bo'lsa, ular nusxalanmaydi, ammo o'chirish jarayoni o'chiriladi. Biror narsa yuzaga kelganda, bu muammo bo'lmasligi mumkin, ammo avtomatlashtirilgan skriptlar uchun bu ma'lumotlar yo'qotilishiga olib kelishi mumkin.
qo'shib qo'ydi muallif Walter Mitty, manba
Ushbu kamchilikka oson echim topish, ro'yxatni matnli fayl sifatida saqlash va keyin nusxa ko'chirish va keyin o'chirish uchun ikki marta xargsdan foydalaning.
qo'shib qo'ydi muallif David M. Perlman, manba

(1) topilgan ikkita misoldan foydalanib,

Har doim cpio (1)

(cd "$soure" && find … | cpio -pdVmu "$destination")

Cpio uchun argumentlarni tekshiring. Men berganlar

2
qo'shib qo'ydi
Ushbu nusxalarni ularni ko'chirish o'rniga fayllar.
qo'shib qo'ydi muallif Valters Vingolds, manba
Bu bo'shliq bilan har qanday fayl nomlarini buzadi.
qo'shib qo'ydi muallif Eric Platon, manba
Muvaffaqiyatli javob berolmasligim mumkin, lekin menga fayllarni bir necha yoki kamroq oldinga siljitishda saqlab qolishimga imkon berdi (fayllarni o'chirib tashlash uchun etarli joy bor). Olib borildi
qo'shib qo'ydi muallif katjam, manba

Siz buni find tomonidan qaytarilgan faylning mutlaq yo'lini maqsad yo'lingizga qo'shish orqali amalga oshirishingiz mumkin:

find "$soure" -type f -mtime "-$days" -print0 | xargs -0 -I {} sh -c '
    file="{}"
    destination="'"$destination"'"
    mkdir -p "$destination/${file%/*}"
    mv "$file" "$destination/$file"'
1
qo'shib qo'ydi
Ushbu kod $ destination tarkibida maxsus belgilar mavjud bo'lsa, bu ichki qismning kengayishiga olib keladi. Ehtimol, siz destination = '\' "$ destination" \ '' ni nazarda tutgan bo'larmidingiz? Bu hali ham ' kodi ustida to'xtaydi. Bundan tashqari, bu /home/maxi/hex/foo o'rniga /home/maxi/home/ketan/hex/foo kabi fayllarni hosil qiladi.
qo'shib qo'ydi muallif Valters Vingolds, manba
@ K.Patel Yo'q, yo'q. U faqat sizning katalog tuzilishini saqlaydi.
qo'shib qo'ydi muallif Eric Platon, manba
Chris endi butun uyini maxiga ko'chiradi
qo'shib qo'ydi muallif Ketankumar Patel, manba

Shu tarzda harakat qilib ko'ring:

IFS=$'\n'
for f in `find "$soure" -type f -mtime "-$days"`;
do
  mkdir -p "$destination"/`dirname $f`;
  mv $f "$destination"/`dirname $f`;
done
0
qo'shib qo'ydi

Better (fastest & without consuming storage space by doing copy instead of move), also is not affected by the file-names if they contain special characters in their names:

export destination
find "$soure" -type f "-$days" -print0 | xargs -0 -n 10 bash -c '
for file in "[email protected]"; do
  echo -n "Moving $file to $destination/"`dirname "$file"`" ... "
  mkdir -p "$destination"/`dirname "$file"`
  \mv -f "$file" "$destination"/`dirname "$file"`/ || echo " fail !" && echo "done."
done'

Yoki tezroq, bir vaqtning o'zida bir nechta fayllarni bir nechta CPU uchun "parallel" buyrug'i yordamida ko'chirib o'tkazish:

echo "Move oldest $days files from $soure to $destination in parallel (each 10 files by "`parallel --number-of-cores`" jobs):"
function move_files {
  for file in "[email protected]"; do
    echo -n "Moving $file to $destination/"`dirname "$file"`" ... "
    mkdir -p "$destination"/`dirname "$file"`
    \mv -f "$file" "$destination"/`dirname "$file"`/ || echo " fail !" && echo "done."
  done
}
export -f move_files
export destination
find "$soure" -type f "-$days" -print0 | parallel -0 -n 10 move_files

P.S .: Sizda typo bor, "soure" "manba" bo'lishi kerak. O'zgaruvchining nomini saqladim.

0
qo'shib qo'ydi

Fayllarning soni/kattaligi juda katta bo'lmasa, bu kamroq oqlangan, ammo oson

Fayllarni birgalikda zip arxiviga joylashtiring va keyin -j parametrisiz maqsadga olib tashlang. Odatiy bo'lib, zip katalogning nisbatan tuzilishini yaratadi.

0
qo'shib qo'ydi

Because there seem to be no really easy solution to this and I need it very often, I created this open source utility for linux (requires python): https://github.com/benapetr/smv

Sizga kerak bo'lgan narsaga erishish uchun uni qanday qilib ishlatishingiz mumkinligini bir necha usullar mavjud, lekin ehtimol bu eng oddiy narsa shunday bo'ladi:

 # -vf = verbose + force (doesn't stop on errors)
smv -vf `find some_folder -type f -mtime "-$days"` target_folder

Bundan tashqari uni quruq rejimda ishlatishingiz mumkin, shunda u hech narsa qilmaydi, balki nima qilishini bosib chiqaradi

smv -rvf `find some_folder -type f -mtime "-$days"` target_folder

Yoki fayllar ro'yxati argumentlarni kiritish uchun juda uzun bo'lsa va siz har bir fayl uchun pythonni bajarishga qarshi bo'lmasangiz, unda

find "$soure" -type f -mtime "-$days" -exec smv {} "$destination" \;

Umid qilamanki bu sizga yordam beradi

0
qo'shib qo'ydi