মেকফাইলে ফাইল উপস্থিত রয়েছে কিনা তা আমি কীভাবে চেক করব যাতে আমি এটি মুছতে পারি?


135

আমার পরিষ্কার বিভাগে Makefileআমি স্থায়ীভাবে মোছার আগে ফাইলটি উপস্থিত আছে কিনা তা যাচাই করার চেষ্টা করছি। আমি এই কোডটি ব্যবহার করি তবে আমি ত্রুটিগুলি পাই।

এতে দোষ কী?

 if [ -a myApp ]
 then
     rm myApp
 fi

আমি এই ত্রুটি বার্তা পেয়েছি

 if [ -a myApp ]
 /bin/sh: Syntax error: end of file unexpected (expecting "then")
 make: *** [clean] Error 2

মাই অ্যাপটি কি ভেরিয়েবল বা প্রকৃত ফাইলের নাম?
বাগফিন্ডার

মাই অ্যাপ্লিকেশনটি হ'ল মাই অ্যাপ্লিকেশন অর্থাৎ বিল্ড প্রক্রিয়া দ্বারা ফাইলের নাম।
আব্রুজ্জো ফোর্টাল ই ই জিন্তেল

5
আপনি যদি ফাইলটি উপস্থিত না থাকেন তবে কেবল থামানো এড়াতে চান, rm -rf myAppবিকল্প হতে পারে। অথবা -rm myApprm থেকে ত্রুটি উপেক্ষা করার জন্য একটি ড্যাশ ( ) দিয়ে কমান্ডটি পূর্ববর্তী করা (এটি তবে কুৎসিত বার্তা প্রিন্ট করবে)।
thomasa88

1
আপনার সমস্যাটি হ'ল একটি নিয়মে প্রতিটি লাইনকে আলাদা কমান্ড হিসাবে আচরণ করে এবং পৃথকভাবে শেলের কাছে প্রেরণ করে। এটি কেবল নিজেরাই চালানো `যদি [-a মাই অ্যাপ] 'চালানোর মতো। আপনি যদি এই ত্রুটিটি পান তবে আপনার কাছে এমন একটি সমাধান দরকার যা লাইনগুলিকে একটিতে ব্যবহার করে (ব্যবহার করে) বা যা প্রতিটি লাইনের সাথে অপরটির সাথে পৃথক হয়ে শেষ হয়। নীচে এইগুলির বেশ কয়েকটি এখন রয়েছে।
মাইকেল

উত্তর:


40

দ্বিতীয় শীর্ষ উত্তরে উল্লেখ করা হয়েছে ifeq, তবে এটি উল্লেখ করতে ব্যর্থ হয়েছে যে এগুলি অবশ্যই লক্ষ্য নামের হিসাবে একই স্তরে থাকতে হবে, উদাহরণস্বরূপ, কোনও ফাইল বর্তমানে উপস্থিত না থাকলে কেবল ডাউনলোড করতে হবে, নিম্নলিখিত কোডটি ব্যবহার করা যেতে পারে:

download:
ifeq (,$(wildcard ./glob.c))
    curl … -o glob.c
endif

# THIS DOES NOT WORK!
download:
    ifeq (,$(wildcard ./glob.c))
        curl … -o glob.c
    endif

যতক্ষণ না আমি ব্যাকস্ল্যাশ যোগ করেছি until `
ফাইয়ের

3
এই উত্তরটি কিছুটা অদ্ভুত হবে; মেকফিলটি প্রক্রিয়া করা হলে ফাইল চেক হয় তবে লক্ষ্যটি মেক দ্বারা তৈরি করা হলে কর্মটি পরে ঘটবে। এর মধ্যে আপনি যদি ফাইলটি মুছে ফেলেন তবে ফাইলটি তৈরি হবে না। এটি পরিষ্কার করার জন্য আমি একটি সম্পাদনা রেখেছি।
মাইকেল

অনেক ধন্যবাদ! ম্যানুয়ালটি পড়ে এই বিষয়টি পরিষ্কার ছিল না।
কেভিন বুশস

207

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

 ifeq ($(UNAME),Darwin)
     SHELL := /opt/local/bin/bash
     OS_X  := true
 else ifneq (,$(wildcard /etc/redhat-release))
     OS_RHEL := true
 else
     OS_DEB  := true
     SHELL := /bin/bash
 endif 

হালনাগাদ:

আমি একটি উপায় খুঁজে পেয়েছি যা আমার পক্ষে সত্যই কাজ করছে:

ifneq ("$(wildcard $(PATH_TO_FILE))","")
    FILE_EXISTS = 1
else
    FILE_EXISTS = 0
endif

4
এটি চেষ্টা করে দেখুন, তবে আমি পেয়ে Makefile:133: *** unterminated call to function `wildcard': missing `)'. Stop.
যাচ্ছি

1
ওয়াইল্ডকার্ডের দুর্দান্ত ব্যবহার, সুতরাং এটি নিজেরাই মেকফিল দিয়ে করা যায়। ঝরঝরে :)
অনুপ

3
$(wildcard pattern)আসলে কি করে তা বুঝতেও সহায়তা করে। লিঙ্ক দেখুন
ড্যান ড্যান

1
আরও সংক্ষিপ্ত:FILE_EXISTS := $(or $(and $(wildcard $(PATH_TO_FILE)),1),0)
ক্যামাস্টার

2
আপনি যদি সাইগউইনের অধীনে উইন্ডোজে চালাচ্ছেন, তবে এইভাবে ওয়াইল্ডকার্ড ব্যবহার করে ফাইলের নামের সাথে সংবেদনশীল কোনও মিল রয়েছে, তাই যদি ফাইলটি বিদ্যমান থাকে তবে পথের চেয়ে আলাদা ক্ষেত্রে থাকলে এটি সন্ধান করতে পারে না। মেকফিলের মধ্যে এই আচরণটিকে ওভাররাইড করার কোনও উপায় বলে মনে হচ্ছে না।
রজার স্যান্ডার্স

59

সমস্যাটি যখন আপনি একাধিক লাইনের উপরে আপনার আদেশটি বিভক্ত করেন। সুতরাং, আপনি \উপরের মত ধারাবাহিকতার জন্য লাইনের শেষে এটিকে ব্যবহার করতে পারেন বা &&ব্যাশে অপারেটরের সাথে এক লাইনে সমস্ত কিছু পেতে পারেন ।

তারপরে আপনি testফাইলটি উপস্থিত থাকলে পরীক্ষা করার জন্য একটি কমান্ড ব্যবহার করতে পারেন , উদাহরণস্বরূপ:

test -f myApp && echo File does exist

-f file সত্য যদি ফাইল বিদ্যমান থাকে এবং নিয়মিত ফাইল হয়।

-s file যদি ফাইল বিদ্যমান থাকে এবং শূন্যের চেয়ে বড় আকার থাকে তবে সত্য True

বা না:

test -f myApp || echo File does not exist
test ! -f myApp && echo File does not exist

testসমতূল্য [কমান্ড।

[ -f myApp ] && rm myApp   # remove myApp if it exists

এবং এটি আপনার মূল উদাহরণ হিসাবে কাজ করবে।

দেখুন: help [বা help testআরও সিনট্যাক্সের জন্য।


4
আমি upvote হবে, কিন্তু আপনি সতর্ক করে না যে -sএটি একটি বিশেষ ক্ষেত্রে exists and has a size greater than zero। লিখিত হিসাবে প্রশ্নটি আকার-অজ্ঞেয়গত, তাই test -eকোনও ফাইল বা -dডিরেক্টরি ব্যবহার করে অস্তিত্ব পরীক্ষা করা উচিত । খালি ফাইলগুলি (আরও ভাল মেয়াদের প্রয়োজনে) সূচক / সেন্ডিনেল হিসাবে বিশেষত কার্যকর হতে পারে যা এর জন্য বেশ প্রাসঙ্গিক হতে পারে make
আন্ডারস্কোর_

পরামর্শের জন্য ধন্যবাদ. -fএটি ব্যবহার করা বেশি সাধারণ হিসাবে ডিফল্টরূপে পরিবর্তিত হয়েছে।
কেনারব

আমি কিভাবে testউইন্ডোজ পেতে পারি ?
থোয়া

3
এটি কাজ করার জন্য আপনাকে || trueশেষে যুক্ত করতে হবে যাতে ফাইল উপস্থিত না থাকলে কমান্ডটি সত্য হয়ে যায়।
jcubic

2
@ অ্যান্ড্রুম্যাকেনজি test -f myApp || CMD, লক্ষ্য করুন ||, সুতরাং যদি -fব্যর্থ হয় - উপস্থিত না থাকে ( ||), তবে কমান্ডটি চালান। এটা বোঝা যায় না?
কেনারব

50

ধারাবাহিকতার জন্য এটি লাইনটির শেষ প্রান্তে ব্যাকস্ল্যাশ লাগতে পারে (যদিও এটি সম্ভবত মেক সংস্করণের উপর নির্ভর করে):

if [ -a myApp ] ; \
then \
     rm myApp ; \
fi;

2
মনে হচ্ছে একটি মেকফিল সিনট্যাক্স না? sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/...
holms

@ হোলস এটি একটি বাশ সিনট্যাক্স। নতুন লাইনগুলি এড়িয়ে যাওয়ার মাধ্যমে এটি এটিকে একক ব্যাশ কমান্ড হিসাবে পরিচালনা করতে দেয়। ডিফল্টরূপে makeএকটি নতুন লাইনে একটি নতুন ব্যাশ কমান্ড হবে। \ লাইন শেষে প্রচুর পরিমাণে থাকার বিরক্তি ব্যতীত এর প্রধান সতর্কতাটি হ'ল প্রতিটি কমান্ড অবশ্যই সমাপ্ত করা উচিত ;যা অন্যথায় বাশে অন্তর্ভুক্ত থাকবে।
ফ্লুনগো

1
সঠিক উত্তরটি হোলস দ্বারা দেওয়া হয়েছে। '\' বা ওয়াইল্ডকার্ড উভয়ই ঠিক এই উদ্দেশ্যে নয়। আপনি ওয়াইল্ডকার্ড ব্যবহার করার কারণটি কোডের স্পষ্টতার জন্য। এই পদ্ধতিটি কেবল কম পঠনযোগ্য নয়, এটি সিনট্যাক্স ত্রুটিগুলির প্রবণতাও বেশি।
মৈত্রেয়

1
লিংক প্রদান করা @holms আর কাজ করে না, ব্যবহার gnu.org/software/make/manual/make.html#Conditionals পরিবর্তে
Fero

এটি একটি দুর্দান্ত উত্তর কারণ এটি মূল প্রশ্নকারী যা করেছে তার সাথে যা ভুল রয়েছে তার সাথে এটি মেলে এবং মেকফিল শুরু হওয়ার পরিবর্তে লক্ষ্যটি তৈরির সময় ফাইলটি উপস্থিত রয়েছে কিনা তার উপর নির্ভর করে এটি কাজ করবে যা বেশিরভাগ লোকেরা প্রত্যাশা করে এবং বেশিরভাগ সময় চাই কয়েকটি অদ্ভুত ক্ষেত্রে @cnst থেকে উত্তর আরও ভাল হবে।
মাইকেল

30

বা এটি কেবল একটি লাইনে রাখুন, যেমন makeএটি পছন্দ করে:

if [ -a myApp ]; then rm myApp; fi;

এটি এক্ষেত্রে দুর্দান্ত উত্তর (এবং উচিৎ হওয়া উচিত) তবে কর্মগুলি আরও জটিল হলে এত ভাল কাজ করবে না, এক্ষেত্রে কেবল using ব্যবহার করতে স্যুইচ করুন
মাইকেল

[-a myApp] &&mm অ্যাপ্লিকেশন
রবিন হু

14

একটি সেমিকোলন অনুপস্থিত

if [ -a myApp ];
then
  rm myApp
fi

তবে, আমি ধরে নিয়েছি যে কোনও ত্রুটি বার্তা রোধ করতে আপনি মুছে ফেলার আগে অস্তিত্বের জন্য যাচাই করছেন। যদি তা হয় তবে আপনি কেবল rm -f myAppকোন "বাহিনী" মুছতে পারেন তা ব্যবহার করতে পারেন , অর্থাত্ ফাইলটি উপস্থিত না থাকলে ত্রুটি হয় না।


1
আমি যা করতে চেয়েছিলাম ঠিক সেটাই। অনেক ধন্যবাদ.
আব্রুজ্জো ফোর্টাল ই ই জিন্তেল

1
এটি কোনও মেকফাইলে কাজ করবে না কারণ যদি এটি এখনও একাধিক লাইনে ছড়িয়ে থাকে - আপনাকে এটি একটি লাইনে রাখতে হবে বা use এস ব্যবহার করতে হবে। এমনকি আপনি যদি যোগ করেছেন তবে আপনি এখনও কিছু আধা-কলোন অনুপস্থিত।
মাইকেল

13
FILE1 = /usr/bin/perl
FILE2 = /nofile

ifeq ($(shell test -e $(FILE1) && echo -n yes),yes)
    RESULT1=$(FILE1) exists.
else
    RESULT1=$(FILE1) does not exist.
endif

ifeq ($(shell test -e $(FILE2) && echo -n yes),yes)
    RESULT2=$(FILE2) exists.
else
    RESULT2=$(FILE2) does not exist.
endif

all:
    @echo $(RESULT1)
    @echo $(RESULT2)

মৃত্যুর ফলাফল:

bash> make
/usr/bin/perl exists.
/nofile does not exist.

এটি আমাকে সহায়তা করেছিল, আমি মনে করি যে কেউ কেউ মিস করেছেন যে ওপি মেকফাইল সম্পর্কে জিজ্ঞাসা করেছিল। "&& এর প্রতিধ্বনি-হ্যাঁ" কেন প্রয়োজনীয় তা আমি বুঝতে পারি নি। ব্যাখ্যা: যদি পরীক্ষা -২০ প্রদান করে (যদি পাওয়া না যায়) তবে শেল ইকো কমান্ডটি কার্যকর করবে না এবং তাই ইফিকে
ব্র্যাড ড্রে

আমি মনে করি আপনি আপনার ব্যাখ্যা বিবৃতিতে এটি সঠিকভাবে বুঝতে পেরেছেন।
রবিন হু

@ ব্র্যাডড্রে - এনএল ছাড়াই স্ট্রিংয়ের echo -n yesসাফল্যের পরিবর্তন ঘটে । তারপর হার্ড কোডেড সঙ্গে এটি তুলনা করতে পারবেন । সমস্ত কারণ শেল কমান্ড থেকে সাফল্যের স্থিতি নয়, একটি স্ট্রিং তুলনা করতে চায়। testyesifeqyesifeq
জেসি চিশল্ম

8

একটি লাইন সমাধান:

   [ -f ./myfile ] && echo exists

ত্রুটি ক্রিয়া সহ একটি লাইন সমাধান:

   [ -f ./myfile ] && echo exists || echo not exists

আমার make cleanনির্দেশনায় ব্যবহৃত উদাহরণ :

clean:
    @[ -f ./myfile ] && rm myfile || true

এবং make cleanসর্বদা কোনও ত্রুটি বার্তা ছাড়াই কাজ করে!


3
শুধু @rm -f মাইফাইল করুন। "-F" পতাকাটির কারণে, "আরএম" ফাইলটি উপস্থিত রয়েছে কি নেই তা নির্বিশেষে 0 দিয়ে প্রস্থান করবে।
আলেক্সি পোলনস্কি

বা, -rm myfileকোনও ত্রুটি উপেক্ষা করার জন্য নেতৃত্বের ড্যাশ বলছে।
জেসি চিশল্ম

1
আমার ক্ষেত্রে, || <ত্রুটি অ্যাকশন> সমস্যার সৃষ্টি করেছে। আপনার চূড়ান্ত উদাহরণ, যেখানে আপনি ফাইলটি উপস্থিত না থাকলে সত্য ফিরে এসেছেন, এটি সুন্দরভাবে সম্বোধন করেছিলেন। ধন্যবাদ!
ফ্লিক করুন

আমার জন্য মাইফাইলে যাওয়ার পথটি অ্যাডাস্ট্রোফের সাথে থাকতে হবে ('):@[ -f 'myfile' ] && rm myfile
স্টেন

0
test ! -f README.md || echo 'Support OpenSource!' >> README.md

"যদি README.md না উপস্থিত থাকে তবে কিছুই করবেন না (এবং সফলভাবে প্রস্থান করুন) Otherwise

আপনি যদি এর &&পরিবর্তে ব্যবহার ||করেন তবে ফাইলটি উপস্থিত না থাকলে আপনি একটি ত্রুটি তৈরি করেন:

Makefile:42: recipe for target 'dostuff' failed
make: *** [dostuff] Error 1

0

আমি চেষ্টা করছিলাম:

[ -f $(PROGRAM) ] && cp -f $(PROGRAM) $(INSTALLDIR)

এবং ইতিবাচক ক্ষেত্রে কাজ করেছে তবে আমার উবুন্টু বাশ শেল এই সত্যকে কল করে এবং অনুলিপিটিতে বিরতি দেয়:

[ -f  ] && cp -f  /home/user/proto/../bin/
cp: missing destination file operand after '/home/user/proto/../bin/'

এই ত্রুটিটি পাওয়ার পরে, আমি গুগল করছি কীভাবে কোনও ফাইল তৈরির মধ্যে রয়েছে কিনা তা পরীক্ষা করে দেখুন এবং এটিই উত্তর ...


0
ifneq ("$(wildcard $(PATH_TO_FILE))","")
    FILE_EXISTS = 1
else
    FILE_EXISTS = 0
endif

উপরে পোস্ট করা এই সমাধানটি সবচেয়ে ভাল কাজ করে। তবে নিশ্চিত হয়ে নিন যে আপনি PATH_TO_FILE অ্যাসাইনমেন্ট যেমন,

PATH_TO_FILE = "/usr/local/lib/libhl++.a" # WILL NOT WORK

এটাই হবে

PATH_TO_FILE = /usr/local/lib/libhl++.a

-2

@ চিহ্ন-উইলকিনের উত্তরগুলির মত উত্তরগুলি lines ব্যবহার করে লাইন চালিয়ে যেতে এবং; এগুলি শেলের মধ্যে শেষ করতে বা @ একরব থেকে এটি একটি লাইনে পরিবর্তন করা ভাল এবং এই সমস্যাটি সমাধান করবে।

মূল সমস্যাটির একটি সহজ উত্তর রয়েছে (@ অ্যালেক্সি-পোলনস্কি নির্দেশিত হিসাবে)। আর-এম-ফ্ল্যাগটি ব্যবহার করুন যাতে এটি কোনও ত্রুটিটিকে ট্রিগার না করে

rm -f myApp

এটি সহজ, দ্রুত এবং আরও নির্ভরযোগ্য। স্ল্যাশ এবং খালি ভেরিয়েবলটি শেষ না হওয়ার জন্য কেবল সাবধান হন

rm -f / $ (myappPath) # এটি কখনও করবেন না

আপনি আপনার সিস্টেম মোছা শেষ হতে পারে।


1
ওপি'র ফাইল মুছে ফেলার জন্য এটি একটি উত্তম উত্তর, তবে আমি নিশ্চিত যে বেশিরভাগ লোকেরা যারা এই প্রশ্নটি আবিষ্কার করেন তারা আসলে কোনও ফাইল মুছে ফেলার জন্য খুঁজছেন না; এটি প্রকৃতপক্ষে প্রমাণিত হয় যে বেশিরভাগ উত্তর এমনকি উল্লেখ rmকরে না; বিটিডাব্লু, আমি নিশ্চিত যে rm -f /$(myAppPath)এটি কোনও ক্ষতি করবে না, হয়ও, কারণ /এটি একটি ডিরেক্টরি এবং এটি -rঅনুপস্থিত।
সিএনএস

এটি কোনও সহজ সমাধান নয়। @ সিএনএসটি যেমন বলেছেন, মূল পোস্টারগুলি কেবল একটি করতে না চাওয়ার কারণ থাকতে পারে rm -f, উদাহরণস্বরূপ তারা rmকোনও পরিবর্তনশীল করতে চায় ।
ড্যান এনগুইন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.