বাশ: স্পেস সহ ফাইলগুলি সরানো


10

আমি যখন কোনও একক ফাইলকে ফাইলের নামের ফাঁকে ফাঁকে স্থানান্তরিত করি তখন এটি এভাবে কাজ করে:

$ mv "file with spaces.txt" "new_place/file with spaces.txt"

এখন আমার কাছে ফাইলগুলির একটি তালিকা রয়েছে যাতে স্পেস থাকতে পারে এবং আমি সেগুলি সরাতে চাই। উদাহরণ স্বরূপ:

$ echo "file with spaces.txt" > file_list.txt
$ for file in $(cat file_list.txt); do mv "$file" "new_place/$file"; done;

mv: cannot stat 'file': No such file or directory
mv: cannot stat 'with': No such file or directory
mv: cannot stat 'spaces.txt': No such file or directory

প্রথম উদাহরণটি কেন কাজ করে তবে দ্বিতীয়টি ডوز করে না? আমি কীভাবে এটি কাজ করতে পারি?

উত্তর:


20

কখনও না, ব্যবহার করুনfor foo in $(cat bar) । এটি একটি ক্লাসিক ভুল, সাধারণত ব্যাশ পিটফল নম্বর 1 নামে পরিচিত। পরিবর্তে আপনার ব্যবহার করা উচিত:

while IFS= read -r file; do mv -- "$file" "new_place/$file"; done < file_list.txt

যখন আপনি চালাতে forলুপ, ব্যাশ এটা কি লেখা আছে করার wordsplitting প্রযোজ্য হবে, যার মানে হল a strange blue cloudপঠিত হিসেবে করা হবে a, strange, blueএবং cloud:

$ cat files 
a strange blue cloud.txt
$ for file in $(cat files); do echo "$file"; done
a
strange
blue
cloud.txt

তুলনা করা:

$ while IFS= read -r file; do echo "$file"; done < files 
a strange blue cloud.txt

বা এমনকি, আপনি যদি ইউইউসিকে জেদ করেন :

$ cat files | while IFS= read -r file; do echo "$file"; done
a strange blue cloud.txt

সুতরাং, whileলুপটি তার ইনপুটটি পড়বে এবং readপ্রতিটি লাইনকে একটি ভেরিয়েবলের জন্য বরাদ্দ করতে ব্যবহার করবে । IFS=সেট শূন্য ইনপুট ক্ষেত্র বিভাজক * , এবং -rবিকল্প readব্যাকস্ল্যাশ বেরিয়ে ব্যাখ্যা (যাতে থেকে এটা স্টপ \tস্ল্যাশ + + হিসাবে গণ্য হবে tনা ট্যাব হিসেবে এবং)। এর --পরে mv"এরপরে সমস্ত কিছুর সাথে আচরণ করুন - একটি আর্গুমেন্ট হিসাবে এবং বিকল্প হিসাবে নয়", যা আপনাকে ফাইলের নামগুলি -সঠিকভাবে শুরু করতে ডিল করতে দেয় ।


* এটি এখানে কঠোরভাবে বলার অপেক্ষা রাখে না, এই দৃশ্যের একমাত্র উপকারটি হ'ল readকোনও অগ্রণী বা পিছনের শ্বেত স্পেস অপসারণ থেকে বিরত রাখে , তবে যখন আপনাকে নতুন লাইনের অক্ষরযুক্ত ফাইলের নাম ব্যবহার করতে হবে তখন তা প্রবেশ করা ভাল অভ্যাস বা সাধারণভাবে, যখন আপনাকে স্বেচ্ছাসেবী ফাইলের নামগুলি মোকাবেলা করতে সক্ষম হতে হবে।


1
ঠিক আছে, আমি কেবল "$ ফাইল" অংশটি থেকে বাঁচার উপায়গুলি খুঁজছিলাম। অন্য কোথাও ত্রুটি আশা করেনি।
মিঃজিংলস 87

@ MrJingles87 আমি জানি I এই এক এক সময়ে সবাই পায় । আপনি যদি এটি সম্পর্কে জানেন না তবে এটি খুব অজ্ঞাতসচেতন।
টেরডন

@ জনকুগেলম্যান হ্যাঁ, সত্যিই ভাল পয়েন্ট। উত্তর সম্পাদিত, ধন্যবাদ।
টেরডন

IFS=ফাইলের নামগুলিতে নতুন লাইনের সাহায্য করবে না। এখানে ফাইলের ফর্ম্যাটটি কেবল নতুন লাইনের সাথে ফাইলের নামগুলিতে অনুমতি দেয় না। IFS=স্থানের নাম বা ট্যাবে শেষ হওয়া ফাইলের নামগুলির জন্য (বা নিউলাইন than আইএফএসের পূর্বে যে কোনও অক্ষর রয়েছে) এর জন্য প্রয়োজন)
স্টাফেন চেজেলাস

এই ব্যাচের সমস্যাটি হ'ল কমান্ড বিকল্পের আউটপুট lsবা তার findসাথে পার্স করার চেষ্টা করা যখন আরও ভাল, আরও নির্ভরযোগ্য উপায় করা যায়। $(cat file)সঠিক হয়ে গেলে ঠিক হয়ে যাবে। কিছুক্ষণ পড়ার লুপের সাথে এটি "সঠিকভাবে করা" যতটা কঠিন, এটি যেমন + $ (...) একটির সাথে রয়েছে। আমার উত্তর দেখুন।
স্টাফেন চেজেলাস

11

যে $(cat file_list.txt)মত POSIX শাঁস মধ্যে bashতালিকা প্রেক্ষাপটে বিভক্ত + + উল্লিখিত glob অপারেটর আছে ( zshশুধু বিভক্ত অংশ হিসেবে আপনি আশা করতে চাই)।

এটি $IFS(ডিফল্টরূপে, এসপিসি , টিএবি এবং এনএল) চরিত্রগুলিতে বিভক্ত হয় এবং আপনি গ্লোব্বিং পুরোপুরি বন্ধ না করে গ্লোব করে does

এখানে, আপনি কেবল নিউলাইনে বিভক্ত করতে চান এবং গ্লোব অংশটি চান না, তাই এটি হওয়া উচিত:

IFS='
' # split on newline only
set -o noglob # disable globbing

for file in $(cat file_list.txt); do # split+glob
  mv -- "$file" "new_place/$file"
done

while readখালি লাইনগুলি বাতিল করতে, একটি অনুসরণযোগ্য নিরবচ্ছিন্ন লাইন সংরক্ষণ এবং স্টিডিন সংরক্ষণের mv(উদাহরণস্বরূপ অনুরোধের ক্ষেত্রে প্রয়োজনীয়) সংরক্ষণ করার সুবিধাও রয়েছে (একটি লুপের উপরে )।

ফাইলটির সম্পূর্ণ সামগ্রীটি মেমরিতে সংরক্ষণ করতে হবে (বেশ কয়েকবার শেল bashএবং লাইক সহ zsh) বেশিরভাগ ক্ষেত্রেই এর অসুবিধা রয়েছে ।

কিছু শাঁস (সঙ্গে ksh, zshএবং একটি ক্ষুদ্রতর ব্যাপ্তি bash), আপনার সাথে নিখুত করতে $(<file_list.txt)পরিবর্তে $(cat file_list.txt)

একটি while readলুপ দিয়ে সমতুল্য করতে, আপনার প্রয়োজন হবে:

while IFS= read <&3 -r file || [ -n "$file" ]; do
  {
    [ -n "$file" ] || mv -- "$file" "new_place/$file"
  } 3<&-
done 3< file_list.txt

বা সাথে bash:

readarray -t files < file_list.txt &&
for file in "${files[@]}"
  [ -n "$file" ] || mv -- "$file" "new_place/$file"
done

বা সাথে zsh:

for file in ${(f)"$(<file_list.txt)"}
  mv -- "$file" "new_place/$file"
done

বা জিএনইউ সহ mvএবং zsh:

mv -t -- new_place ${(f)"$(<file_list.txt)"}

বা GNU mvএবং GNU xargsএবং ksh / zsh / bash সহ:

xargs -rd '\n' -a <(grep . file_list.txt) mv -t -- new_place

বাশ / পসিক্স শেলগুলির একটি পরিবর্তনশীল উদ্ধৃতি ভুলে যাওয়ার সুরক্ষা সম্পর্কিত প্রভাবগুলিতে অনর্থক বিস্তৃতি ছাড়ার অর্থ কী সম্পর্কে আরও পড়ুন


আমি মনে করি আপনার স্বীকৃতি দেওয়া উচিত, যদিও $(cat file_list.txt)এটি পুনরাবৃত্ত হওয়ার আগে পুরো ফাইলটি মেমরিতে while read ...পড়ে whereas এটি বড় ফাইলগুলির জন্য একটি সমস্যা হতে পারে।
চেপনার

@chepner। ভাল যুক্তি. যোগ করা হয়েছে।
স্টাফেন চেজেলাস

1

স্ক্রিপ্ট লেখার পরিবর্তে, আপনি সন্ধান করতে পারেন ..

 find -type f -iname \*.txt -print0 | xargs -IF -0 mv F /folder/to/destination/

ক্ষেত্রে ফাইলগুলি ফাইলের মধ্যে অবস্থিত থাকে তবে আপনি নিম্নলিখিতটি করতে পারেন:

cat file_with_spaces.txt | xargs -IF -0 mv F /folder/to/destination

দ্বিতীয় যদিও নিশ্চিত না ..

গুডলাক


3
আপনি যদি ব্যবহার করেন তবে আপনি সমস্ত কিছুর জন্যও findব্যবহার করতে পারেন find। কেন xargsএটি এনে ? find -type f -iname '*.txt' -exec mv {} /folder/to/destination/
টেরডন

xargs এখানে সন্ধানের ফলাফলগুলি সহজেই পরিচালনা করে: -আমি প্রতিটি ফলাফল একটি ভেরিয়েবল এফের জন্য বরাদ্দ করি যখন 0 এবং মুদ্রণ0 কেবল গ্যারান্টি দিয়ে ফাঁকা ফাইলগুলি এড়ায় না। এবং -0 xargs ফলাফল থেকে বাঁচতে বাধা দেয়। স্পেস দিয়ে কীভাবে এক্সেক আচরণ করে তা নিশ্চিত নন ..
নোয়েল অ্যালেক্স মাকুমুলি

2
-execস্বেচ্ছাসেবী ফাইল নামগুলির সাথে পুরোপুরি আচরণ করে (এতে স্পেস, নিউলাইনস বা অন্য কোনও অদ্ভুততা রয়েছে এমনগুলি অন্তর্ভুক্ত)। আমি জানি কীভাবে xargsকাজ করে, ধন্যবাদ :) যখনই findইতিমধ্যে আপনার জন্য এটি করতে পারে আমি কেবল একটি পৃথক কমান্ড কল করার বিষয়টি দেখতে পাই না । এটির সাথে কোনও ভুল নেই, কেবল অদক্ষ।
টেরডন

@ স্টারডোনুই ঠিক বলেছেন .. -অজুপাতিক {path / পথ / গন্তব্যটি সুচারুভাবে কাজ করে .. আমি আরও অতিরিক্ত জিনিসগুলির কারণে আমি এটি করতে সক্ষম হওয়ায় জার্সগুলিকে পছন্দ করি।
নোয়েল অ্যালেক্স মাকুমুলি

xargsক্লোবারবারিং স্টিডিনের অপূর্ণতাও রয়েছে (যা mvতার প্রম্পটের জন্য প্রয়োজন)। @ টার্ডনের সমাধানের সাথেও একটি সমস্যা xargsপ্রক্রিয়া প্রতিস্থাপন সহ জিএনইউ এবং শাঁস দিয়ে, এর উপশম করা যায়xargs -0IF -a <(find...) mv F /dest
স্টাফেন চেজেলাস

-1
FIRST INSTALL 

apt-get install chromium-browser

apt-get install omxplayer

apt-get install terminator

apt-get install nano (if not already installed)

apt-get install zenity (if not already installed)

THEN CREATE A BASH SCRIPT OF ALL OF THESE PERSONALLY WRITTEN SCRIPTS. 

MAKE SURE THAT EVERY SHELL SCRIPT IS A .sh FILE ENDING EACH ONE OF THESE IS SCRIPTED TO OPEN UP A DIRECTORY FOR YOU TO FIND AND PICK WHAT YOU WANT. 

IT RUNS A BACKGROUND TERMINAL & ALLOWS YOU TO CONTROL THE SONG OR MOVIE.  

MOVIE KEYS ARE AS FOLLOWS; p or space bar for pause, q for quit, - & + for sound up and down, left arrow and right arrow for skipping forward and back. 

MUSIC PLAYER REALLY ONLY HAS A SKIP SONG AND THAT IS CTRL+C AND IF THAT IS THE LAST SONG OR ONLY SONG THEN IT SHUTS DOWN AND THE TERMINAL GOES AWAY.


****INSTRUCTIONS TO MAKE THE SCRIPTS****
- OPEN UP A TERMINAL 

- CD TO THE DIRECTORY YOU WANT THE SCRIPTS TO BE
cd /home/pi/Desktop/

- OPEN UP THE NANO EDITOR WITH THE TITLE OF SHELL YOU WANT
sudo nano Movie_Player.sh

- INSIDE NANO, TYPE OR COPY/PAST (REMEMBER THAT IN TERMINAL YOU NEED TO CTRL+SHIFT+V) THE SCRITP

- SAVE THE DATA WITH CTRL+O
ctrl+o

- HIT ENTER TO SAVE AS THAT FILE NAME OR DELETE THE FILE NAME THEN TYPE NEW ONE JUST MAKE SURE IT ENDS IN .sh THEN HIT ENTER

- NEXT YOU NEED TO SUDO CHMOD IT WITH +X TO MAKE IT CLICKABLE AS A BASH
sudo chmod +x Movie_Player.sh

- FINALLY RUN IT TO TEST EITHER BY DOUBLE CLICKING IT AND CHOOSING "EXECUTE IN TERMINAL" OR BY ./ IT IN TERMINAL
./Movie_Player.sh

YOU ARE NOW GOOD TO PICK A MOVIE OR SELECT A SONG OR ALBUM AND ENJOY!  




**** ALL OF THESE SCRIPTS ACCOUNT FOR SPACES IN THE FILENAME 
SO YOU CAN ACCESS "TOM PETTY" OR "SIXTEEN STONE" WITHOUT NEEDING THE " _ " BETWEEN THE WORDS.




-------WATCH A MOVIE SCRIPT ------- (

#! / বিন / ব্যাশ

ফাইল =zenity --title "Pick a Movie" --file-selection

"$ {ফাইল [0]}" এ ফাইলের জন্য

ওমেক্সপ্লেয়ারটি "$ {ফাইল [0]।" সম্পন্ন করুন

--------LISTEN TO A SONG -------

! / বিন / ব্যাশ

ফাইল =zenity --title "Pick a Song" --file-selection

"$ {ফাইল [0]}" এ ফাইলের জন্য

"$ {ফাইল [0]।" খেলা সম্পন্ন হয়ে গেছে

--------LISTEN TO AN ALBUM ---------- SONGS IN ORDER

! / বিন / ব্যাশ

থেকে DIR =zenity --title "Pick a Album" --file-selection --directory

"$ {DIR [0] in" তে DIR এর জন্য

সিডি করুন "$ {ডিআইআর [0]}" && সন্ধান করুন। -type f -name ' .ogg' -o -name ' .mp3' | সাজান - রূপান্তর-সাজান | ডিআইআর পড়ার সময়; সম্পন্ন হয়ে গেছে "play DIR" খেলুন

--------LISTEN TO AN ALBUM WITH SONGS IN RANDOM ORDER --------

! / বিন / ব্যাশ

থেকে DIR =zenity --title "Pick a Album" --file-selection --directory

"$ {DIR [0] in" তে DIR এর জন্য

সিডি করুন "$ {ডিআইআর [0]}" && সন্ধান করুন। -type f -name ' .ogg' -o -name ' .mp3' | ডিআইআর পড়ার সময়; সম্পন্ন হয়ে গেছে "play DIR" খেলুন


মার্কডাউন সম্পর্কে পড়ুন এবং আপনার উত্তরে কিছু মেক আপ প্রয়োগ করুন। এবং দয়া করে ব্যাখ্যা করুন কেন এটি প্রশ্নের উত্তর দেয়। এবং বন্ধ করবেন না !!!

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