mv: не може стати Немає такого файлу чи каталогу в скрипті оболонки


16

Я написав сценарій для переміщення деяких файлів з однієї папки в іншу папку, але я отримав таку помилку, я перевірив 2 папки і помітив, що на 1 папці є такі файли, а в іншій таких файлів немає, але чому всі вони показують "mv Не може стати. Немає таких файлів чи каталогів "

    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.42.17.124_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/195.113.161.13_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.199.61.205_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.51.218.235_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/213.73.40.105_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/41.225.7.4_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/83.230.127.122_tcp.folder/data/*': No such file or directory
    [esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/
    [esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/
    129.88.70.226   132.187.230.1    138.96.116.22   155.185.54.250   192.38.109.144  193.136.227.163  193.175.135.61  195.113.161.13  83.230.127.122
    130.104.72.200  132.227.62.122   147.83.29.232   156.17.10.52     192.42.43.22    193.137.173.218  193.205.215.74  212.199.61.205
    131.130.69.164  132.252.152.194  148.81.140.193  157.181.175.249  192.43.193.71   193.144.21.131   193.226.19.30   212.51.218.235
    131.188.44.102  134.151.255.180  152.66.245.162  160.78.253.31    193.1.170.136   193.145.46.243   194.199.68.165  213.73.40.105
    131.254.208.10  138.48.3.203     152.81.47.4     192.114.4.3      193.136.166.56  193.166.160.98   194.42.17.124   41.225.7.4

сценарій:

    list=`ls dest_folder`
    cd dest_folder
    cwd=`pwd`
    for folder in $list;do
            mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
    done

Я запустив це /home/esolve/project/capture/tcp_50x50/


1
Будь ласка, покажіть відповідні частини сценарію.
Мат

Я оновив своє запитання і додав сценарій, дякую!
містерії

Вам потрібно додати -rдо mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}?
ProfessionalAmateur

немає -rваріанту дляmv
misteryes

Відповіді:


25
mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

Цитати ( ') там заважають оболонці робити глобул. Команда *передається буквально mvкоманді, яка виходить з ладу, оскільки не знаходить файли, викликані *у вказаних каталогах.

Змініть це на:

mv "${cwd}/${folder}/data"/* "${cwd}/${folder}"

(Подвійні лапки, щоб запобігти проблемам, якщо у вас коли-небудь є ім'я каталогу з пробілами. *Поза межами лапок.)

Ви все одно отримаєте помилки в порожніх каталогах. (Така ж причина: якщо файл не знаходить відповідності шаблону, він передає сам шаблон як аргумент команді.)


Подвійні лапки мають сенс, але навіщо мені ставити *поза цитатами?
Сіббс азартні ігри

Якщо ви хочете, щоб він розширився, він вам потрібен за межами @SibbsGambling
Мат

8

У коді є кілька проблем:

list=`ls dest_folder`

Ви зберігаєте вихідні дані lsбез символів для нових рядків $list. lsвиводить список імен файлів, розділених символами нового рядка. newlineє настільки ж дійсним символом, як і будь-який в імені файлу, тому вихід не може бути надійно використаний. Наприклад, lsвихід для каталогу, який містить aі bтакий же, як і для каталогу, який містить один названий файл a<newline>b.

 cd dest_folder

Ви не перевіряєте провал цієї команди. Загалом, ви повинні перевірити стан виходу команд, але це особливо стосується cd, оскільки решта команд припускають, що ви перебуваєте в тому новому каталозі, і це може мати драматичні наслідки, коли ви цього не зробите.

cwd=`pwd`

Оболонки POSIX вже підтримують шлях (один) до поточного каталогу в $PWDзмінній, тому вам тут не потрібно використовувати pwd(особливо в загальному випадку, оскільки підміна команд видалить з контуру символи нового рядка). Крім того, mvприймає відносні шляхи, тому вам не потрібно будувати абсолютний шлях.

for folder in $list;do

Залишаючи змінну без котирування - це оператор split + glob в оболонках. Тобто, вміст змінної розділено (на розділювачі, згадані в $IFSспеціальних правилах для пробілів), і кожен елемент, що виникає в результаті розщеплення, шукає символи підстановки, щоб їх можна було розширити до списку відповідних файлів.

Тут ви хочете розщеплення, але тільки для символів нового рядка, і ви не хочете, щоб глобус, тому вам потрібно буде відключити його:

 IFS='
 '; set -f
 for folder in $list
   mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

Знову ж таки, залишаючи змінну без котирування оператор split + glob . Тут ви не хочете жодного, тому вам потрібно цитувати ці змінні.

Як уже згадувалося, подвійні символи розширюються лише тоді, коли вони не цитуються, і вам потрібно *вийти з лапок. Якщо ви відключили глобалізацію раніше set -f, вам потрібно буде відновити її set +fперед тим, як викликати цю команду.

Набагато кращим способом її написання було б:

cd dest_folder &&
  for folder in */;do
    mv -- "${folder}data/"* "$folder"
  done

Кілька приміток, хоча:

  • Це виключить приховані папки і не перемістить приховані файли з dataпапок.
  • Ми не перевіряємо, чи не переглядаються файли в процесі (можливо, ви хочете додати цю -iопцію до mv).
  • Використовуючи */, ми перебираємо лише каталоги , але це включає також символічні посилання на каталоги. Якщо ви цього не хочете, вам потрібно буде додати [ -L "${folder%/}" ] && continueвнутрішню петлю.
  • Якщо в ній немає прихованої папки, */вона розшириться до себе, тож ви отримаєте повідомлення про помилку, mvсказавши, що не може знайти названий файл */data/*. Аналогічно, якщо в жодній з папок that-folder/data/*не існує прихованого файлу, ви отримаєте повідомлення про помилку, яке не існує.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.