অনুসন্ধানগুলি ব্যবহার করে ফাইলগুলি সরানোর সময় ডিরেক্টরি কাঠামো সংরক্ষণ করুন


22

আমি নিম্নলিখিত স্ক্রিপ্টটি তৈরি করেছি যা উত্স ডিরেক্টরি থেকে গন্তব্য ডিরেক্টরিতে সংজ্ঞায়িত হিসাবে পুরানো দিনের ফাইলগুলিকে সরিয়ে দেয়। এটি নিখুঁতভাবে কাজ করছে।

#!/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"

এই স্ক্রিপ্টটি ফাইলগুলিকে দুর্দান্তভাবে সরিয়ে দেয়, এটি উত্স সাবডাইরেক্টরির ফাইলগুলিও সরায় তবে এটি গন্তব্য ডিরেক্টরিতে সাব-ডিরেক্টরিকে তৈরি করে না। আমি এটিতে এই অতিরিক্ত বৈশিষ্ট্যটি প্রয়োগ করতে চাই।

উদাহরণ সহ

/home/ketan     : source directory

/home/ketan/hex : source subdirectory

/home/maxi      : destination directory

আমি যখন এই স্ক্রিপ্টটি চালনা করি, তখন এটি হেক্সের ফাইলগুলি ম্যাক্সি ডিরেক্টরিতেও সরিয়ে দেয়, তবে আমার প্রয়োজন একই হেক্সটি ম্যাক্সি ডিরেক্টরিতে তৈরি করা উচিত এবং তার ফাইলগুলি সেখানে একই হেক্সে সরিয়ে নেওয়া উচিত।

উত্তর:


13

চলমান পরিবর্তে mv /home/ketan/hex/foo /home/maxi, আপনার দ্বারা উত্পাদিত পাথের উপর ভিত্তি করে লক্ষ্য ডিরেক্টরিটি পরিবর্তিত করতে হবে find। এই যদি প্রথম উৎস নির্দেশিকাতে পরিবর্তন এবং চালানোর সহজ find .। এখন আপনি কেবলমাত্র উত্পাদিত প্রতিটি আইটেমের জন্য গন্তব্য ডিরেক্টরিটি প্রেন্ডিং করতে পারেন findfind … -execকনটেন্টেশন সম্পাদন করার জন্য আপনাকে কমান্ডের একটি শেল চালাতে হবে এবং প্রয়োজনে লক্ষ্য ডিরেক্টরিটি তৈরি করতে হবে।

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" {} \;

মনে রাখবেন যে $destinationবিশেষ অক্ষর থাকলে ইস্যু উদ্ধৃতি এড়ানোর জন্য , আপনি কেবল এটি শেল স্ক্রিপ্টের মধ্যে প্রতিস্থাপন করতে পারবেন না। আপনি এটি পরিবেশে রফতানি করতে পারেন যাতে এটি অভ্যন্তরের শেলটিতে পৌঁছে যায় বা আপনি এটি একটি যুক্তি হিসাবে পাস করতে পারেন (এটি আমিই করেছি)। আপনি shকলকে গ্রুপবদ্ধ করে কার্যকর করার সময়টি কিছুটা সাশ্রয় করতে পারেন :

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" {} +

অন্যথা, zsh, আপনি ব্যবহার করতে পারেন zmvফাংশন , এবং .এবং m উল্লিখিত glob কোয়ালিফায়ার শুধুমাত্র করার অধিকার তারিখ সীমার মধ্যে নিয়মিত ফাইল মেলে। আপনাকে একটি বিকল্প mvফাংশন পাস করতে হবে যা প্রয়োজনে প্রথমে লক্ষ্য ডিরেক্টরি তৈরি করে।

autoload -U zmv
mkdir_mv () {
  mkdir -p -- $3:h
  mv -- $2 $3
}
zmv -Qw -p mkdir_mv $source/'**/*(.m-'$days')' '$destination/$1$2'

for x do, আপনি ;সেখানে নিখোঁজ পেয়েছেন :)। এছাড়াও, আপনি কী অর্জন করতে চেয়েছিলেন তা সম্পর্কে আমার কোনও ধারণা নেই $0তবে আমি তা নিশ্চিত হয়েছি sh:)।
মাইচা গার্নি

@ মাইচাগার্নি for x; doপ্রযুক্তিগতভাবে পসিক্স -অনুগত ( ব্যাকরণ পরীক্ষা করুন ) নন , তবে আধুনিক শেলগুলি উভয়কেই অনুমতি দেয় for x doএবং for x; do; কিছু পুরানো বোর্ন শেল কুঁচকেনি for x; do। আধুনিক শেলগুলিতে, সাথে sh -c '…' arg0 arg1 arg2 arg3, arg0হয়ে ওঠে $0, arg1হয়ে যায় $1ইত্যাদি you আপনি যদি $0হতে চান তবে আপনার shলিখতে হবে sh -c '…' sh arg1 arg2 arg3। আবার কিছু বোর্ন শেল ভিন্নভাবে আচরণ করেছে, তবে পসিক্স এটি নির্দিষ্ট করে specif
গিলস 'অশুচি হওয়া বন্ধ করুন'

pushdcdএটি আরও ভাল পছন্দ হিসাবে মনে হচ্ছে , এটি বর্তমান পরিবেশে কম অনুপ্রবেশকারী হিসাবে।
jpmc26

16

আমি জানি findনির্দিষ্ট ছিল, কিন্তু এটি একটি কাজের মতো মনে হচ্ছে rsync

আমি প্রায়শই নিম্নলিখিত ব্যবহার করি:

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

আপনি যদি কোনও নির্দিষ্ট ফাইল-টাইপের ( উদাহরণস্বরূপ ) ফাইলগুলি সরাতে চান তবে এখানে একটি ভাল উদাহরণ রয়েছে :

rsync -rv --include '*/' --include '*.js' --exclude '*' --prune-empty-dirs Source/ Target/

অন্যের সমাধানগুলির চেয়ে অনেক বেশি ক্লিনার :)
গিলিয়াম

2
আমি এটি --remove-source-filesসহায়ক বলে মনে করেছি, যার ফলে ফাইলগুলি অনুলিপি করার পরিবর্তে কার্যকরভাবে স্থানান্তরিত হয়। এটি rsync এর দুর্দান্ত ব্যবহার aw
টম

3

আপনি এটি দুটি দৃষ্টান্ত ব্যবহার করে করতে পারেন (1)

সিপিও সর্বদা আছে (1)

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

সিপিওর জন্য আর্গুমেন্টগুলি পরীক্ষা করুন। আমি যা দিয়েছি


1
এটি হোয়াইটস্পেসের সাথে কোনও ফাইলের নাম ভাঙবে।
ক্রিস ডাউন

1
এটি ফাইলগুলি সরানোর পরিবর্তে অনুলিপি করে।
গিলস 'অশুচি হওয়া বন্ধ করুন'

একটি নিখুঁত উত্তর নাও হতে পারে, তবে এটি আমাকে আরও বা কম সোজা এগিয়ে এগিয়ে যাওয়ার পথগুলি সংরক্ষণের ফাইলগুলিতে স্থানান্তরিত করতে সহায়তা করেছিল (ফাইলগুলি মুছার পরে মুছার জন্য আমার পর্যাপ্ত জায়গা রয়েছে)। আপভোটড
আহেহেটেম

3

এটি তেমন দক্ষ নয়, তবে কোডটি আমার মতে, পড়া এবং বুঝতে সহজ, যদি আপনি কেবল ফাইলগুলি অনুলিপি করেন এবং তারপরে মুছুন।

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

বিজ্ঞপ্তি: স্বয়ংক্রিয় ক্রিয়াকলাপের জন্য @ এমভি দ্বারা ত্রুটি আবিষ্কার হয়েছে:

দুটি পৃথক অপারেশন ব্যবহার ঝুঁকিপূর্ণ। অনুলিপি অপারেশন করার সময় যদি কিছু ফাইল 7 দিনেরও বেশি বয়স্ক হয়ে যায় তবে সেগুলি অনুলিপি করা হবে না তবে মোছা অপারেশন দ্বারা সেগুলি মুছে ফেলা হবে। ম্যানুয়ালি একবার কিছু করার জন্য এটি কোনও সমস্যা নাও হতে পারে, তবে স্বয়ংক্রিয় স্ক্রিপ্টগুলির জন্য এটি ডেটা ক্ষতি হতে পারে


2
দুটি পৃথক অপারেশন ব্যবহার ঝুঁকিপূর্ণ। অনুলিপি অপারেশন করার সময় যদি কিছু ফাইল 7 দিনেরও বেশি বয়স্ক হয়ে যায় তবে সেগুলি অনুলিপি করা হবে না তবে মোছা অপারেশন দ্বারা সেগুলি মুছে ফেলা হবে। ম্যানুয়ালি একবার কিছু করার জন্য এটি কোনও সমস্যা নাও হতে পারে, তবে স্বয়ংক্রিয় স্ক্রিপ্টগুলির জন্য এটি ডেটা ক্ষতি হতে পারে।
এমভি

2
এই ত্রুটির সহজ সমাধানটি একবার অনুসন্ধান চালানো, পাঠ্য ফাইল হিসাবে তালিকাটি সংরক্ষণ করা এবং অনুলিপিটি করার জন্য xargs ব্যবহার করা এবং তারপরে মুছুন।
ডেভিড এম পার্লম্যান

1

আপনি findআপনার গন্তব্য পথে ফিরে আসা ফাইলটির পরম পথটি সংযোজন করে এটি করতে পারেন :

find "$soure" -type f -mtime "-$days" -print0 | xargs -0 -I {} sh -c '
    file="{}"
    destination="'"$destination"'"
    mkdir -p "$destination/${file%/*}"
    mv "$file" "$destination/$file"'

ক্রিস এখন পুরো বাড়িটি ম্যাক্সিতে চলে গেছে
কেতন প্যাটেল

@ কে.কেপ্যাটেল না, এটি হয় না। এটি কেবল আপনার ডিরেক্টরি কাঠামো রাখে।
ক্রিস ডাউন

$destinationবিশেষ অক্ষরগুলি থাকলে এটি বিরতি দেয় কারণ এটি অভ্যন্তরীণ শেলটিতে প্রসারিত হয়। আপনি বলতে চাইছেন destination='\'"$destination"\''? যে এখনও বিরতি '। এছাড়াও এটি এর /home/maxi/home/ketan/hex/fooপরিবর্তে ফাইল তৈরি করে /home/maxi/hex/foo
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

0

আরও ভাল (দ্রুত ও পরিবর্তনের পরিবর্তে অনুলিপি করে স্টোরেজ স্পেস গ্রহণ না করে), ফাইল-নামগুলিতে তাদের নামের বিশেষ অক্ষর থাকলে তাদের দ্বারাও প্রভাবিত হবে না:

export destination
find "$soure" -type f "-$days" -print0 | xargs -0 -n 10 bash -c '
for file in "$@"; 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'

বা দ্রুত, "সমান্তরাল" কমান্ডটি ব্যবহার করে বহু-সিপিইউ-র জন্য একই সাথে অনেকগুলি ফাইল সরিয়ে নিয়ে যাওয়া:

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 "$@"; 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

পিএস: আপনার টাইপো আছে, "স্যুর" "উত্স" হওয়া উচিত। ভেরিয়েবলের নাম রেখেছি।


0

ফাইলের সংখ্যা / আকার খুব বড় না হলে এটি কম মার্জিত তবে সহজ

আপনার ফাইলগুলিকে একত্রে একটি zipসংরক্ষণাগারে জিপ করুন এবং তারপরে -jবিকল্প ছাড়াই গন্তব্যে আনজিপ করুন । ডিফল্টরূপে, জিপ আপেক্ষিক ডিরেক্টরি কাঠামো তৈরি করবে।


0

এইভাবে চেষ্টা করুন:

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

0

কারণ এর কোনও সহজ সমাধান বলে মনে হচ্ছে না এবং এটির প্রায়শই প্রয়োজন আমার, আমি লিনাক্সের জন্য এই উন্মুক্ত উত্সটি তৈরি করেছি (পাইথন প্রয়োজন): https://github.com/benapetr/smv

আপনার যা প্রয়োজন তা অর্জন করতে আপনি এটি কীভাবে ব্যবহার করতে পারেন তার বেশ কয়েকটি উপায় রয়েছে তবে সম্ভবত সবচেয়ে সহজ কিছু হতে পারে:

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

আপনি অতিরিক্ত এটি শুকনো মোডে চালাতে পারেন যাতে এটি কিছু না করে তবে কী করে তা মুদ্রণ করে

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

অথবা যদি ফাইলগুলির তালিকাটি আর্গুমেন্ট লাইনে ফিট করার জন্য দীর্ঘ হয় এবং আপনি প্রতিটি একক ফাইলের জন্য পাইথন চালাতে আপত্তি করেন না, তবে

find "$soure" -type f -mtime "-$days" -exec smv {} "$destination" \;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.