প্রদত্ত এক্সটেনশান সহ সমস্ত ফাইল সন্ধান করা হচ্ছে যার মূল নামটি পিতামাতার নির্দেশিকার নাম


9

আমি পুনরাবৃত্তভাবে *.pdfএকটি ডিরেক্টরিতে প্রতিটি ফাইল সন্ধান করতে চাই ~/fooযার মূল নামটি ফাইলের প্যারেন্ট ডিরেক্টরিটির নামের সাথে মেলে।

উদাহরণস্বরূপ, ধরুন যে ডিরেক্টরি কাঠামোটি ~/fooএরকম দেখাচ্ছে

foo
├── dir1
│   ├── dir1.pdf
│   └── dir1.txt
├── dir2
│   ├── dir2.tex
│   └── spam
│       └── spam.pdf
└── dir3
    ├── dir3.pdf
    └── eggs
        └── eggs.pdf

আমার কাঙ্ক্ষিত আদেশটি চালানো ফিরে আসত

~/foo/dir1/dir1.pdf
~/foo/dir2/spam/spam.pdf
~/foo/dir3/dir3.pdf
~/foo/dir3/eggs/eggs.pdf

এটি কি সম্ভব findবা অন্য কোনও মূল ইউটিলিটি ব্যবহার করে সম্ভব ? আমি ধরে নিই যে এটি -regexবিকল্পটি ব্যবহার করে করণীয় findতবে সঠিক প্যাটার্নটি কীভাবে লিখবেন তা আমি নিশ্চিত নই।


হ্যাঁ, আমি এখন একটি উদাহরণ উপহাস করব।
ব্রায়ান ফিটজপ্যাট্রিক

1
@ ইনিয়ান একটি উদাহরণ যুক্ত করেছে। এটা কি সাহায্য করে?
ব্রায়ান ফিটজপ্যাট্রিক

উত্তর:


16

জিএনইউ সহ find:

find . -regextype egrep -regex '.*/([^/]+)/\1\.pdf'
  • -regextype egrep উদাহরণস্বরূপ স্টাইল রেজেক্স ব্যবহার করুন।
  • .*/ পিতামাতার নির্দেশের সাথে মেলে।
  • ([^/]+)/ একটি দলে পিতামাতার দির সাথে মেলে।
  • \1\.pdfbackreferenceপিতা পিতা হিসাবে ফাইলের নাম মেলে ব্যবহার করুন।

হালনাগাদ

একজন (একজনের জন্য আমি) ভাবতে পারি যে .*এটি যথেষ্ট লোভী, /পিতামাতার মিল থেকে বাদ দেওয়া অপ্রয়োজনীয় :

find . -regextype egrep -regex '.*/(.+)/\1\.pdf'

উপরের কমান্ডটি ভাল কাজ করবে না, কারণ এটি ম্যাথ করে ./a/b/a/b.pdf:

  • .*/ ম্যাচ ./
  • (.+)/ ম্যাচ a/b/
  • \1.pdf ম্যাচ a/b.pdf

খুব ঠান্ডা. আশা করি আমি এটিকে ভালভাবেই পুনরায় সাজিয়ে তুলতে পারতাম।
ব্রায়ান ফিটজপ্যাট্রিক

অথবা find . -regex '.*/\([^/]*\)/\1\.pdf'তারপরে এটি বিএসডির সাথেও কাজ করবে find
স্টাফেন চেজেলাস

7

find .. -exec sh -c ''বেস নামটি মিলানোর জন্য শেল কনস্ট্রাক্টস ব্যবহার করার জন্য Theতিহ্যগত লুপ বৈকল্পিক এবং উপরের তাত্ক্ষণিক পথটি নীচে করা হবে।

find foo/ -name '*.pdf' -exec sh -c '
    for file; do 
        base="${file##*/}"
        path="${file%/*}"
        if [ "${path##*/}" =  "${base%.*}" ]; then
            printf "%s\n" "$file" 
        fi
    done' sh {} +

পৃথক প্যারামিটার বিস্তৃতি ভাঙ্গতে

  • fileকমান্ড .pdfথেকে ফিরে আসা ফাইলের পুরো পথ রয়েছেfind
  • "${file##*/}"শেষের পরে কেবলমাত্র অংশটি থাকে যা কেবলমাত্র /ফাইলের ভিত্তি নাম
  • "${file%/*}"চূড়ান্ত পর্যন্ত পথ অন্তর্ভুক্ত /অর্থাৎ ফলাফলের বেসনাম অংশ বাদে
  • "${path##*/}"ভেরিয়েবল /থেকে শেষের পরে অংশটি অন্তর্ভুক্ত করে path, অর্থাত্ ফাইলের বেসনামের উপরে তাত্ক্ষণিক ফোল্ডার পাথ
  • "${base%.*}".pdfএক্সটেনশন সরানো সহ বেসনামের অংশ রয়েছে

সুতরাং যদি এক্সটেনশনবিহীন বেস নামটি উপরের তাত্ক্ষণিক ফোল্ডারের নামের সাথে মিলে যায় তবে আমরা পথটি মুদ্রণ করি।


7

ইনিয়ান এর উত্তরের বিপরীত অর্থাত্ ডিরেক্টরিগুলি অনুসন্ধান করুন এবং তারপরে দেখুন যে তারা কোনও নির্দিষ্ট নামের সাথে কোনও ফাইল ধারণ করে কিনা।

নিম্নলিখিতটি ডিরেক্টরি সম্পর্কিত সম্পর্কিত ফাইলগুলির পাথের নামগুলি মুদ্রণ করে foo:

find foo -type d -exec sh -c '
    for dirpath do
        pathname="$dirpath/${dirpath##*/}.pdf"
        if [ -f "$pathname" ]; then
            printf "%s\n" "$pathname"
        fi
    done' sh {} +

${dirpath##*/}ডিরেক্টরি পথের ফাইল নাম অংশ দ্বারা প্রতিস্থাপন করা হবে, এবং দ্বারা প্রতিস্থাপন করা যেতে পারে $(basename "$dirpath")

শর্ট সার্কিট সিনট্যাক্স পছন্দ করে এমন লোকদের জন্য:

find foo -type d -exec sh -c '
    for dirpath do
        pathname="$dirpath/${dirpath##*/}.pdf"
        [ -f "$pathname" ] && printf "%s\n" "$pathname"
    done' sh {} +

এটি এইভাবে করার সুবিধা হ'ল ডিরেক্টরিগুলির চেয়ে আপনার পিডিএফ ফাইল থাকতে পারে। যদি কেউ ছোট সংখ্যা (ডিরেক্টরিগুলির সংখ্যা) দ্বারা ক্যোয়ারিকে সীমাবদ্ধ রাখে তবে জড়িত পরীক্ষার সংখ্যা হ্রাস হয় are

উদাহরণস্বরূপ, যদি কোনও একক ডিরেক্টরিতে 100 পিডিএফ ফাইল থাকে, তবে এটি কেবলমাত্র ডিরেক্টরিগুলির মধ্যে 100 টি ফাইলের নাম পরীক্ষার চেয়ে কেবল তার মধ্যে একটি সনাক্ত করার চেষ্টা করবে।



2

এটি নির্দিষ্ট করা হয়নি, তবে কেউ আগ্রহী হলে এখানে নিয়মিত প্রকাশ ছাড়াই একটি সমাধান।

আমরা ব্যবহার করতে পারি find . -type f, তাহলে কাজে লাগাতে শুধু ফাইল পেতে dirnameএবং basenameশর্তাধীন লিখতে। ইউটিলিটিগুলির নিম্নলিখিত আচরণ রয়েছে:

$ find . -type f
./dir2/spam/spam.pdf
./dir2/dir2.tex
./dir3/dir3.pdf
./dir3/eggs/eggs.pdf
./dir1/dir1.pdf
./dir1/dir1.txt

basenameশেষের পরে ফাইলের নামটি দেয় /:

$ for file in $(find . -type f); do basename $file; done
spam.pdf
dir2.tex
dir3.pdf
eggs.pdf
dir1.pdf
dir1.txt

dirnameফাইনাল পর্যন্ত পুরো পথ দেয় /:

$ for file in $(find . -type f); do dirname $file; done
./dir2/spam
./dir2
./dir3
./dir3/eggs
./dir1
./dir1

অতএব, basename $(dirname $file)ফাইলের পিতামহিত ডিরেক্টরি দেয়।

$ for file in $(find . -type f); do basename $(dirname $file) ; done
spam
dir2
dir3
eggs
dir1
dir1

সমাধান

শর্তসাপেক্ষ গঠনের জন্য উপরের সংমিশ্রণ করুন "$(basename $file)" = "$(basename $(dirname $file))".pdf, তারপরে findযদি প্রতিটি শর্তসাপেক্ষে সত্য হয় তবে কেবলমাত্র প্রতিটি ফলাফল মুদ্রণ করুন ।

$ while read file; do if [ "$(basename "$file")" = "$(basename "$(dirname "$file")")".pdf ]; then echo $file; fi done < <(find . -type f)
./dir2/spam/spam.pdf
./dir3/dir3.pdf
./dir3/eggs/eggs.pdf
./dir1/dir1.pdf
./Final Thesis/grits/grits.pdf
./Final Thesis/Final Thesis.pdf

উপরের উদাহরণে, আমরা সেই ক্ষেত্রে চিকিত্সা করার জন্য নামে ফাঁকা জায়গায় একটি ডিরেক্টরি / ফাইল যুক্ত করেছি (মন্তব্যগুলিতে @ কুশালানন্দকে ধন্যবাদ)


এটি দুর্ভাগ্যক্রমে Final Thesis.pdf(একটি স্থান সহ) ফাইলের নামগুলি ছিন্ন করবে ।
কুসালানন্দ

@ কুসালানন্দ ফিক্সড
user1717828

0

আমি নিতে ব্যাশ globbing, স্ট্রিং উপর সহজ লুপ পরীক্ষা উপর কোনো দিন খুঁজুন প্রোগ্রাম। আমাকে অযৌক্তিক বলুন, এবং যদিও এটি সাবঅপটিমাল হতে পারে তবে এ জাতীয় সহজ কোডটি আমার পক্ষে কৌতুক করে: পাঠযোগ্য এবং পুনরায় ব্যবহারযোগ্য, এমনকি সন্তোষজনকও !. সুতরাং এর মিশ্রণের পরামর্শ দেওয়ার জন্য আমাকে অনুমতি দিন:

• ব্যাশ globstar : for f in ** ; do ... ** বর্তমান ডিরেক্টরির মধ্যে প্রত্যেক ফাইল এবং সব সাবফোল্ডার উপর লুপ .. আপনার বর্তমান সেশন মধ্যে globstar স্থিতি চেক করতে: shopt -p globstar। সক্রিয় globstar করার জন্য: shopt -s globstar

File "ফাইল" উচ্চতা : পিডিএফ -এর if [[ $(file "$f") =~ pdf ]]; then ... জন্য প্রকৃত ফাইল ফর্ম্যাটটি পরীক্ষা করা - কেবলমাত্র ফাইলের এক্সটেনশনের জন্য পরীক্ষার চেয়ে আরও দৃust়

Name বেসনাম, ডাইরনাম : তত্ক্ষণাত্ তার উপরে ডিরেক্টরিটির নামের সাথে ফাইলের নামের তুলনা করতে। basenameফাইলের নামটি দেয় - dirnameপুরো ডিরেক্টরিটি ফেরত দেয় - দুটি ফাংশন একত্রিত করে কেবলমাত্র ম্যাচিং ফাইল যুক্ত একটি ডিরেক্টরি ফেরত দেয়। আমি স্ট্রিং ম্যাচিংয়ের জন্য = using ব্যবহার করে একটি সাধারণ পরীক্ষা করার জন্য আমি প্রত্যেককে একটি ভেরিয়েবল ( _mydir এবং _myf ) এ রেখেছি

একটি সূক্ষ্মতা: বর্তমানের ডিরেক্টরিতে শর্টকাটটিও "" নামের সাথে মিলে যাওয়া ফাইল এড়াতে ফাইলের যে কোনও "বিন্দু" মুছে ফেলুন "" - আমি পরিবর্তনশীল _myf- এ সরাসরি স্ট্রিং প্রতিস্থাপন ব্যবহার করেছি : ${_myf//./}- খুব মার্জিত নয় তবে এটি কার্যকর। সাথে আউটপুট পূর্ববর্তী দ্বারা বর্তমান ফোল্ডার পূর্ণ পাথ দিয়ে একসঙ্গে - ইতিবাচক ম্যাচ প্রতিটি ফাইল পথে ফিরে আসবে $(pwd)/

কোড

for f in ** ; do
  if [[ $(file "$f") =~ PDF ]]; then
    _mydir="$(basename $(dirname $f))" ; 
    _myf="$(basename $f)" ; 
    [[ "${_myf//./}" =~ "$_mydir" ]] && echo -e "$(pwd)/$f" ; 
  fi ; 
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.