Windows এ একটি "^" (ক্যারেট) ধারণ করে এমন ফাইলগুলির সাথে প্রক্রিয়া করা হচ্ছে


1

আমি একটি ধারণকারী ধারণকারী ফাইল প্রক্রিয়াকরণ সমস্যা হচ্ছে "^" (ক্যারেট)।

আমি যা দেখছি তা হল যে যদি ফাইল নামগুলি মূল্যায়ন করার সময় আমি ডবল উদ্ধৃতি ব্যবহার করি তবে "ক্যারেটের" দ্বিগুণ হবে। যদি আমি ডবল কোটগুলি ব্যবহার করি না, তবে ফাইলের নামগুলিতে "ক্যারেটগুলির" দ্বিগুণ (সংরক্ষিত) নয়, তবে কিছু ফাইলের নাম এম্বেডেড স্পেস রয়েছে, তাই আমাকে দুটি উদ্ধৃতি দিয়ে ফাইলের নামগুলি মূল্যায়ন করতে হবে।

উদাহরণস্বরূপ, আমার একটি ফোল্ডার আছে যা কিছু ফাইল রয়েছে:

G:\Test-folder\Abcxyz 1.txt
G:\Test-folder\Abcxyz2.txt
G:\Test-folder\Abcxyz3.txt
G:\Test-folder\Abc^xyz 1.txt
G:\Test-folder\Abc^xyz2.txt
G:\Test-folder\Abc^xyz3^.txt

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

@echo off

rem collect the filenames
dir /s /b "G:\Test-folder\ab*" > "G:\Test-folder\list.txt"

rem Note: here I have an opportunity to inspect and modify the filenames as necessary, but I have not found any modifications that solve this problem. 

rem process each file
for /f "usebackq delims=" %%f in ("G:\Test-folder\list.txt") do call :work "%%~f"

@echo.
@echo Back: f1="%f1%"
@echo.
@echo.

@echo Running again, with "setlocal enabledelayedexpansion".
@echo.

for /f "usebackq delims=" %%f in ("G:\Test-folder\list.txt") do call :work2 "%%~f"

@echo.
@echo Back: f2="%f2%"
@echo.
goto :EOF



:work
rem :work

set "f1=%~1"

if exist "%f1%" goto :dostuff

@echo.
@echo File "%f1%" not found.
@echo       %f1%
@echo      "%~1"
@echo       %~1
@echo.
goto :EOF

:dostuff
rem do some stuff :dostuff
@echo File "%f1%" found.
goto :EOF



:work2
rem :work2

setlocal enabledelayedexpansion
set "f2=%~1"

if exist "!f2!" goto :dostuff2

@echo.
@echo File "!f2!" not found.
@echo       !f2!
@echo      "%~1"
@echo       %~1
@echo.
endlocal
goto :EOF

:dostuff2
rem do some stuff :dostuff2
@echo File "!f2!" found.
endlocal
goto :EOF

এই স্ক্রিপ্টটি চালানো, আমি নিম্নলিখিত আউটপুট পেতে পারি:

File "G:\Test-folder\Abcxyz 1.txt" found.
File "G:\Test-folder\Abcxyz2.txt" found.
File "G:\Test-folder\Abcxyz3.txt" found.

File "G:\Test-folder\Abc^^xyz 1.txt" not found.
      G:\Test-folder\Abc^xyz 1.txt
     "G:\Test-folder\Abc^^xyz 1.txt"
      G:\Test-folder\Abc^xyz 1.txt


File "G:\Test-folder\Abc^^xyz2.txt" not found.
      G:\Test-folder\Abc^xyz2.txt
     "G:\Test-folder\Abc^^xyz2.txt"
      G:\Test-folder\Abc^xyz2.txt


File "G:\Test-folder\Abc^^xyz3^^.txt" not found.
      G:\Test-folder\Abc^xyz3^.txt
     "G:\Test-folder\Abc^^xyz3^^.txt"
      G:\Test-folder\Abc^xyz3^.txt


Back: f1="G:\Test-folder\Abc^^xyz3^^.txt"


Running again, with "setlocal enabledelayedexpansion".

File "G:\Test-folder\Abcxyz 1.txt" found.
File "G:\Test-folder\Abcxyz2.txt" found.
File "G:\Test-folder\Abcxyz3.txt" found.

File "G:\Test-folder\Abc^^xyz 1.txt" not found.
      G:\Test-folder\Abc^^xyz 1.txt
     "G:\Test-folder\Abc^^xyz 1.txt"
      G:\Test-folder\Abc^xyz 1.txt


File "G:\Test-folder\Abc^^xyz2.txt" not found.
      G:\Test-folder\Abc^^xyz2.txt
     "G:\Test-folder\Abc^^xyz2.txt"
      G:\Test-folder\Abc^xyz2.txt


File "G:\Test-folder\Abc^^xyz3^^.txt" not found.
      G:\Test-folder\Abc^^xyz3^^.txt
     "G:\Test-folder\Abc^^xyz3^^.txt"
      G:\Test-folder\Abc^xyz3^.txt


Back: f2=""

সুতরাং, উভয় উপায়, সঙ্গে ব্যবহার বা ছাড়া "enabledelayedexpansion", আমি একটি নাম ধারণকারী ফাইল প্রক্রিয়া করতে পারবেন না "^" (ক্যারেট)।

কিভাবে এই ধারনা, অথবা কি আমি ভুল করছি?


1
আমি কি PowerShell একটি বিকল্প হতে পারে জিজ্ঞাসা করতে পারেন? যদি হ্যাঁ, অধিকাংশ পিএস কমান্ড সমর্থন করে literal মত সুইচ Get-Content -literal "D:\abc [def] ^ xyz.txt" যা সব বিশেষ অক্ষর সঙ্গে ফাইল প্রক্রিয়া করতে পারেন
nixda

1
আপনি আপনার ফাইল ফাইল থেকে ডবল ক্যারেট ফালা পারে :work সাবরুটিন। তাই করতে, যোগ করুন set "f1=%f1:^^=^%" ঠিক পরে set কমান্ড। তবে ভাল সমাধান হতে পারে।
and31415

@ নিক্সদা - পাওয়ারশেল সমাধান করার জন্য ধন্যবাদ, আমি এটি চেষ্টা করব। আমি Powershell (এখনো) মধ্যে সব দক্ষ নই, তাই আমি উইন্ডোজ ব্যাচ সমাধান খুঁজছি।
Kevin Fegan

@ এবং 31415 - ধন্যবাদ, আপনার সমাধান আমার জন্য কাজ করে। যদি আপনি এটি একটি উত্তর দিতে, আমি এটা গ্রহণ করব। এটা মজার, আমি আগে এই বৈশিষ্ট্যটি ব্যবহার করেছি, এবং আমি ভেবেছিলাম এটির জন্য আমি এটি চেষ্টা করেছি এবং এটি কাজ করে নি। এটা এখন কাজ করছে.
Kevin Fegan

উত্তর:


2

কিছুক্ষণের জন্য এই খেলার পর, আমি এই কাজের সমাধান নিয়ে এসেছিলাম:

@echo off

rem collect the filenames
dir /s /b "G:\Test-folder\ab*" >"G:\Test-folder\list.txt"

rem process each file
for /f "usebackq delims=" %%f in ("G:\Test-folder\list.txt") do call :work "%%~f"
@echo.

rem Note: I still could not make this work with "setlocal enabledelayedexpansion".

goto :EOF



:work
rem :work

set "f1=%~1"

if exist "%f1%" goto :dostuff

@echo.
@echo File "%f1%" not found.
@echo       %f1%
@echo      "%~1"
@echo       %~1
@echo.

rem Notice that the "action" of this (next) for-loop is: [set "f1=%%~f"]
rem which uses the "for-variable" from the "outer" for-loop: "%%f"
rem instead of the "for-variable" from the "this" for-loop: "%%g"

@for /f "usebackq delims=" %%g in (`echo "dummy"`) do set "f1=%%~f"

if exist "%f1%" goto :dostuff

@echo File "%f1%" not found.
@echo       %f1%
@echo.
goto :EOF

:dostuff
rem do some stuff :dostuff

@echo File "%f1%" found.
for %%g in ("%f1%") do echo name:"%%~ng" extn:"%%~xg" file-size:"%%~zg"
@echo.
goto :EOF

এই স্ক্রিপ্টটি চালানোর আউটপুটটি হল:

File "G:\Test-folder\Abcxyz 1.txt" found.
name:"Abcxyz 1" extn:".txt" file-size:"14"

File "G:\Test-folder\Abcxyz2.txt" found.
name:"Abcxyz2" extn:".txt" file-size:"13"

File "G:\Test-folder\Abcxyz3.txt" found.
name:"Abcxyz3" extn:".txt" file-size:"13"


File "G:\Test-folder\Abc^^xyz 1.txt" not found.
      G:\Test-folder\Abc^xyz 1.txt
     "G:\Test-folder\Abc^^xyz 1.txt"
      G:\Test-folder\Abc^xyz 1.txt

File "G:\Test-folder\Abc^xyz 1.txt" found.
name:"Abc^xyz 1" extn:".txt" file-size:"15"


File "G:\Test-folder\Abc^^xyz2.txt" not found.
      G:\Test-folder\Abc^xyz2.txt
     "G:\Test-folder\Abc^^xyz2.txt"
      G:\Test-folder\Abc^xyz2.txt

File "G:\Test-folder\Abc^xyz2.txt" found.
name:"Abc^xyz2" extn:".txt" file-size:"14"


File "G:\Test-folder\Abc^^xyz3^^.txt" not found.
      G:\Test-folder\Abc^xyz3^.txt
     "G:\Test-folder\Abc^^xyz3^^.txt"
      G:\Test-folder\Abc^xyz3^.txt

File "G:\Test-folder\Abc^xyz3^.txt" found.
name:"Abc^xyz3^" extn:".txt" file-size:"15"

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

আমি পরিবর্তন করার জন্য "sed" ব্যবহার করার চেষ্টা ছিল "^^" একটি একক উদ্ধৃত স্ট্রিং "^", এটার মত:

@for /f "usebackq delims=" %%g in (`echo "%f1%"^|sed -r "s/(\x5e)\1/\1/g"`) do set "f1=%%~g"

আমি ভুলভাবে এই পরিবর্তে টাইপ করেছি:

@for /f "usebackq delims=" %%g in (`echo "%f1%"^|sed -r "s/(\x5e)\1/\1/g"`) do set "f1=%%~f"

আমি সত্যিই বিস্মিত ছিল না (প্রথমে) যখন এটি কাজ করে, কারণ আমি ভাবলাম "sed" প্রত্যাশিত হিসাবে কাজ করছে। তারপর, আমি খেয়াল করেছি যে আমি ভুলের জন্য পরিবর্তনশীল ব্যবহার করেছি: set "f1=%%~f" পরিবর্তে: set "f1=%%~g"যা বিস্ময়কর ছিল।

আমি সঠিক পরিবর্তনশীল ব্যবহার করার জন্য এটি পরিবর্তন: set "f1=%%~g", এটি কাজ করে না শুধুমাত্র এটি খুঁজে।

আমি এই সহ বিভিন্ন সংস্করণ চেষ্টা করেছেন:

@for /f "usebackq delims=" %%g in (`echo "%f1%"`) do set "f1=%%~g"

যার কোন কাজ।

সুতরাং, এটি ভুল কাজ করার জন্য ভুল ব্যবহার করে "অপব্যবহার করা" হয় বলে মনে হয়। এই ক্ষেত্রে এই দরকারী বলে মনে হচ্ছে, যদিও আমি দীর্ঘ সময়কাল কাজ করবে বিশ্বাস করে একটি কঠিন সময় আছে।

এটি আসলেই "দস্তাবেজ" (প্রত্যাশিত) আচরণ, নাকি অন্যের কাছ থেকে শুনতে আগ্রহী।


1

এক Q এবং A তে দুটি অস্পষ্ট উইন্ডোজ ব্যাচ আচরণ আবিষ্কারের জন্য আপনাকে খুশি!

বাচ বা কমান্ড লাইনে কল করে স্ট্রিং আক্ষরিক হিসাবে উদ্ধৃত ক্যারেটগুলির অদ্ভুত সংখ্যা পাস করা অসম্ভব। একটি ব্যাখ্যা ফেজ 6 পাওয়া যাবে) এ কিভাবে উইন্ডোজ কমান্ড ইন্টারপ্রেটার (CMD.EXE) স্ক্রিপ্ট পার্স?

এখানে সমস্যা একটি উদাহরণ। ধরুন একটি স্ক্রিপ্টটিতে নিম্নোক্ত কমান্ড রয়েছে:

call echo Unquoted ^^ "Quoted ^"

প্যাসারের দ্বিতীয় পর্যায় পরে, অব্যবহৃত অংশ পালানোর আচরণের অংশ হিসাবে একটি ক্যারেট খাওয়া। উদ্ধৃত অংশ একা বাকি আছে। কমান্ডটি এখন মনে হচ্ছে:

call echo Unquoted ^ "Quoted ^"

ফেজ 6 এ কল করার সনাক্তকরণের পরে, সমস্ত কের্ট দ্বিগুণ হয়ে যায় এবং নিম্নলিখিত প্রক্রিয়াটি কল প্রক্রিয়া মাধ্যমে গৃহীত হয়:

echo Unquoted ^^ "Quoted ^^"

কল একটি দ্বিতীয় ফেজ 2 মাধ্যমে যায়), যার ফলে:

echo Unquoted ^ "Quoted ^^"

নিম্নলিখিত চূড়ান্ত আউটপুট উত্পাদন:

Unquoted ^ "Quoted ^^"

ফর লুপের সাথে আপনার উদাহরণটি প্রাথমিক পর্যায় 2 কে বাইপাস করে কারণ ভেরিয়েবল বিস্তারের জন্য ফেজ 2 এর পরে ঘটে।


সমাধান - কল মাধ্যমে ক্যারেট ধারণকারী উদ্ধৃত স্ট্রিং অক্ষর পাস করবেন না। একটি বিকল্প কৌশল ব্যবহার করুন। বিভিন্ন অপশন আছে। আমি নীচে কয়েক তালিকাভুক্ত করেছি।

1 ক) সব সময়ে কল ব্যবহার করবেন না। ইচ্ছাকৃতভাবে জটিল কোড তৈরির জন্য আপনি DO এর পরে বন্ধনী ব্যবহার করতে পারেন। এই পর্যন্ত আমার প্রিয় কৌশল দ্বারা, কল স্বাভাবিকভাবেই ধীর কারণ। আপনি যা করতে পারবেন না শুধুমাত্র একমাত্র লুপের মধ্যে GOTO ব্যবহার করুন কারণ এটি অবিলম্বে লুপ প্রসেসিং বন্ধ করবে। যদি আপনি লুপের মধ্যে ভেরিয়েবলগুলি ম্যানিপুলেট করতে চান তবে আপনাকে বিলম্বিত সম্প্রসারণ সক্ষম করতে এবং ব্যবহার করতে হবে।

setlocal enableDelayedExpansion
for ....%%A  in (...) do (
  set "var=%%A"
  echo the value of var=!var!
  ... whatever
)


1B) ফর ফর পরিবর্তনশীল থাকতে পারে!, তাহলে আপনাকে অবশ্যই দুর্নীতি প্রতিরোধে লুপের মধ্যে বিলম্বিত সম্প্রসারণটি বন্ধ এবং বন্ধ করতে হবে।

for ... %%A in (...) do (
  setlocal enableDelayedExpansion
  set "var=%%A"
  echo the value of var=!var!
  ... whatever
  endlocal
)


2A) আপনি যদি সত্যিই কলটি ব্যবহার করতে চান তবে মানটি স্ট্রিং আক্ষরিক রূপে প্রেরণ করবেন না। পরিবর্তে, একটি পরিবেশ পরিবর্তনশীল মান সংরক্ষণ করুন। উল্লেখ্য যে var এর মান বিশেষ অক্ষরগুলির বিরুদ্ধে সুরক্ষার জন্য উদ্ধৃত করা হয়।

for ... %%A in (...) do (
  set var="%%~A"
  call :work
)
exit /b

:work
echo var=%var%
... etc.
exit /b


2b) আমি বিলম্বিত সম্প্রসারণটি ব্যবহার করতে পছন্দ করি যাতে স্ট্রিংয়ের মধ্যে বিশেষ অক্ষরগুলি উদ্ধৃত করা হয় কিনা সে সম্পর্কে আমাকে চিন্তা করতে হবে না। উল্লেখ্য যে var এর মানটি উদ্ধৃত করা হয় না কারণ খোলার উদ্ধৃতিটি SET বিবৃতির মধ্যে পরিবর্তনশীল নামের আগে উপস্থিত হয়।

for ... %%A in (...) do (
  set "var=%%~A"
  call :work
)
exit /b

:work
setlocal enableDelayedExpansion
echo var=!var!
... etc.
exit /b


2C) এমন একটি subroutine লেখার পরিবর্তে শুধুমাত্র একটি পরিবর্তনশীলের সাথে কীভাবে কাজ করতে হয় তা জানেন, আপনি একটি পরিবর্তনশীল হিসাবে নাম পরিবর্তন করতে পারেন। এই বিলম্বিত বিস্তার প্রয়োজন।

for ... %%A in (...) do (
  set "var=%%~A"
  call :work var
)
exit /b

:work
setlocal enableDelayedExpansion
echo %1=!%1!
... etc.
exit /b


3) ভেরিয়েবল "টানেলিং" এর জন্য ব্যবহার করুন তোমার উত্তর । আমি অতীতের এই কৌশলটি ব্যবহার করেছি, কিন্তু এটি আমি পছন্দ করি না কারণ এটি অবাঞ্ছিত। যে কেউ কোডটি লেখার পরে কোড বজায় রাখার চেষ্টা করে সেটি সম্ভবত কী ঘটছে তা বুঝতে পারবে না।

ভেরিয়েবলগুলির জন্য শুধুমাত্র FOR বিবৃতির ডিও লুপের মধ্যে সুযোগ রয়েছে। যখন আপনি লুপ থেকে কল করেন, সুযোগটি শেষ হয়। কিন্তু, আপনি আবিষ্কার করেছেন যে, কলযুক্ত রুটিনের নিজস্ব বিবৃতি থাকলে, পুরোনো ফর ভেরিয়েবলগুলি "যাদুকরী" পুনরায় আবির্ভূত হয়।

for ... %%A in (...) do call :work
exit /b

:work
echo The A variable is no longer in scope: %%A
for %%x in (x) do echo The A variable is back: %%A

ব্যাখ্যাটি যে বৈকল্পিকগুলির জন্য বিশ্বব্যাপী, তবে শুধুমাত্র একটি ডিও লুপের মধ্যে অ্যাক্সেসযোগ্য। এই cryptically সাহায্য সাহায্য সিস্টেমের মধ্যে ব্যাখ্যা করা হয়। আদর্শ help for অথবা for /? সাহায্য পেতে। প্রাসঙ্গিক বিভাগ প্রায় অর্ধেক উপায় নিচে। উদ্ধৃতি শেষ দিকে সাহসী শব্দ নোট করুন।

কিছু উদাহরণ সাহায্য করতে পারে:

FOR / F "eol =; টোকেন = ২3 * delims =,"% আমি (myfile.txt) @echo% i% j   % ট

Myfile.txt প্রতিটি লাইন পার্স, শুরু যে লাইন উপেক্ষা       একটি সেমিকোলন, প্রতিটি লাইন থেকে 2nd এবং 3rd টোকেন পাস       শরীর, কমা এবং / বা স্পেস দ্বারা delimited টোকেন সঙ্গে। জন্য নোটিশ       শরীরের বিবৃতি রেফারেন্স% আমি দ্বিতীয় টোকেন পেতে,% জে পেতে       3 য় টোকেন, এবং% কে 3 র্থ পর বাকি টোকেনগুলি পেতে। জন্য       ফাইলের নাম যা স্পেস ধারণ করে, আপনাকে ফাইল নামগুলি উদ্ধৃত করতে হবে       উদ্ধৃতি চিহ্ন. এই ভাবে ডবল উদ্ধৃতি ব্যবহার করার জন্য, আপনি       usebackq বিকল্প ব্যবহার করতে হবে, অন্যথায় ডবল কোট হবে       পার্স করতে একটি আক্ষরিক স্ট্রিং সংজ্ঞায়িত হিসাবে ব্যাখ্যা করা হয়।

% আমি স্পষ্টভাবে বিবৃতি এবং% j এবং% k মধ্যে ঘোষণা করা হয়       implicitly টোকেন = বিকল্প মাধ্যমে ঘোষণা করা হয়। আপনি নির্দিষ্ট করতে পারেন       টোকেন = লাইনের মাধ্যমে 26 টোকেন, এটি একটি কারণ না করে প্রদান করে       অক্ষর 'z' বা 'z' এর চেয়ে একটি পরিবর্তনশীল উচ্চ ঘোষণা করার প্রচেষ্টা।       মনে রাখবেন, ভেরিয়েবলগুলির জন্য একক অক্ষর, কেস সংবেদনশীল, বিশ্বব্যাপী ,       এবং আপনি যে কোনও সময়ে 52 টিরও বেশি সক্রিয় থাকতে পারবেন না।

আমি যে আচরণের জন্য কখনও দেখেছি তা যতটা সরকারী ডকুমেন্টেশন। খুব রহস্যময়, এবং খুব সহায়ক না। আসলে, যে শেষ অনুচ্ছেদের তথ্য অনেক সহজ ভুল ! দেখ https://stackoverflow.com/a/8520993/1012053 জন্য সর্বাধিক ফর ভেরিয়েবল উপলব্ধ সত্য হিসাবে, এবং ফর ভেরিয়েবল জন্য বৈধ অক্ষর কি।


0

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

@ECHO OFF

DIR /b /s >list.txt

SETLOCAL enabledelayedexpansion
FOR /f "delims=" %%x IN (list.txt) DO IF EXIST "%%x" (@ECHO %%x found) else (@ECHO %%x not found)

ধন্যবাদ, আমি এটি আমার সমাধান চেয়ে সহজ মনে হিসাবে চেষ্টা করব।
Kevin Fegan
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.