LinuxForum.Fans
Тема

Скрипт выполняет задачу не до конца

Автор: vanya999 21 сообщений 4106 просмотров
#351742

Вот задача.
Напишите скрипт, который запускается с двумя аргументами:
- первый аргумент задает имя каталога
- второй аргумент задает имя каталога
и который выполняет следующие действия:
-просматривает текущий каталог
-если в текущем каталога найдены оба каталога, все файлы из первого каталога перемещаются во второй, а из второго - в первый
-если хотя бы один из указанных каталогов не найден, выводится сообщение Directory is not found.

Вот мой вариант (сразу простите за ошибки в синтаксисе, которые могут быть, так как не успел еще linux на виртуалку поставить).
Перед скриптом я создал пустой каталог с именем katalog_tmp

text

!#/bin/bash

PER=2 if [ $# -ne $PER ] then echo "Запустите скрипт заново и наберите с клавиатуры 2 аргумента" exit fi

if [ -e $1] then if [ -e $2] then mv $1 katalog_tmp; mv $1 $2; mv $2 katalog_tmp; else echo "Directory is not found" fi else echo "Directory is not found" fi

То есть по сути мой скрипт
1) Переименовывает папки местами, а не перемещает файлы из одной папки в другую.
2) Скрипт проверяет существование каталогов вообще, а не в текущем каталоге.
Как записать скрипт, что он выполнял СТРОГО поставленные задачи ? Напишите, пожалуйста, как можно проще. Только начали изучать bash. Мало всего знаем пока что.



Пользуйтесь тегами BBCode

#351761
text
#!/bin/sh

if [ -d "$1" ] && [ -d "$2" ]; then tmp="$(mktemp -d)" mv "$1/"* "$tmp" mv "$2/"* "$1" mv "$tmp/"* "$2" rmdir "$tmp" else echo 'Directory is not found.' >&2 exit 1 fi

#351762
XRevan86 написал:
text
#!/bin/sh

if [ -d "$1" ] && [ -d "$2" ]; then tmp="$(mktemp -d)" mv "$1/"* "$tmp" mv "$2/"* "$1" mv "$tmp/"* "$2" rmdir "$tmp" else echo 'Directory is not found.' >&2 exit 1 fi

А вы не могли бы построчно объяснить скрипт ? Не могу многое понять

#351763

vanya999

  1. Проверяем наличие каталогов (кавычки для учёта возможных пробелов):
  2. Создаём временный каталог и записываем вывод mktemp (он пишет название созданного файла/каталога) в переменную;
  3. Перемещаем всё из $1 во временный каталог (звёздочка обязана быть вне кавычек, ибо иначе она экранируется);
  4. Из $2 в $1;
  5. Из временного каталога в $2;
  6. Удаляем временный каталог.
  7. Или:
  8. Пишем в stderr (точнее, перенаправляем из stdout в stderr), что каталога нет, если не найдены $1 и $2 (пустые значения также считаются за не найденные);
  9. Выходим с выходным сигналом 1 (наличие ошибки в работе).
#351764

Немного замечаний:
1) "Если оба каталога найдены в текущем каталоге..." на bash будет выглядывать как-то так:

text
 if [ -d "$PWD/$1" && -d "$PWD/$2" ]; ... 

2) "...то переместить файлы из первого во второй:

text

for i in $1 $2 ; do
    find $i -type f >> "list$i.tmp"
done
while read j; do
    mv $j $2
done << list$1.tmp
rm -f list$1.tmp

Я в шелл-скриптинге далеко не гуру, так что имейте в виду, что могут быть ошибки. Ну и надеюсь, готовое решение сможете извлечь из приведенного кода.

#351765

Спасибо вам огромное ! Выручили. Завтра поставлю виртуалку и буду скрипт проверять. Сегодня пока просто разберу.

#351766

yars

  1. Bourne Shell по умолчанию работает в текущем каталоге, зачем извращаться с $PWD?
  2. Отсутствие учёта пробелов в именах, while запрашивает переменную у пользователя и ещё… короче, оно не работает и не должно работать;
  3. Ах да, всё есть файл, даже каталог является файлом в общем смысле :).
#351769
XRevan86 написал:
yars
  1. Bourne Shell по умолчанию работает в текущем каталоге, зачем извращаться с $PWD?
  2. Отсутствие учёта пробелов в именах, while запрашивает переменную у пользователя и ещё… короче, оно не работает и не должно работать;
  3. Ах да, всё есть файл, даже каталог является файлом в общем смысле :).

1) Ну, вообще, да, промах :-)
2) Кавычки вокруг имен переменных нужно.
3. Я это не проверял, писал "на глаз", отлаживать не на чем. Но, почему оно будет запрашивать имя переменной у пользователя? В bash, по идее, работать должно...

#351770
"yars" написал:
Но, почему оно будет запрашивать имя переменной у пользователя?

А, извини, не заметил, что " << list$1.tmp" относится к while. Тем не менее, использовать файл для таких целей — очень странная затея.

#351774

А по мне, логично. Сохранить списки файлов в обоих каталогах, потом по ним перемещать. Ну сколько людей, столько и мнений, но нужно стремиться к "рационально", а не просто к "правильно". Готов признать, мой вариант нерационален. Хотел, чтобы ТС своими силами дошел до правильного рационального варианта.

#351777
XRevan86 написал:
vanya999
  1. Проверяем наличие каталогов (кавычки для учёта возможных пробелов):
  2. Создаём временный каталог и записываем вывод mktemp (он пишет название созданного файла/каталога) в переменную;
  3. Перемещаем всё из $1 во временный каталог (звёздочка обязана быть вне кавычек, ибо иначе она экранируется);
  4. Из $2 в $1;
  5. Из временного каталога в $2;
  6. Удаляем временный каталог.
  7. Или:
  8. Пишем в stderr (точнее, перенаправляем из stdout в stderr), что каталога нет, если не найдены $1 и $2 (пустые значения также считаются за не найденные);
  9. Выходим с выходным сигналом 1 (наличие ошибки в работе).

По поводу пункта 3. Зачем там нужен слеш и звездочка ? Звездочка, насколько я знаю, является мета символом, указывающий любую последовательность из любых элементов.

#351778

vanya999
Именно, в случае с Bourne Shell звёздочка означает последовательность всех файлов и каталогов :):

text
$ echo /media/*
/media/cdrom /media/cdrom0 /media/user
#351779

XRevan86, в условии буквально сказано, что перемещать нужно все файлы в каталогах, про подкаталоги ни слова ;-)
Потому и find -type f.

#351780
XRevan86 написал:
vanya999
Именно, в случае с Bourne Shell звёздочка означает последовательность всех файлов и каталогов :):
text
$ echo /media/*
/media/cdrom /media/cdrom0 /media/user

То есть идет наш указанный каталог, а дальше адрес может быть любым ?

#351781
"yars" написал:
про подкаталоги ни слова

Поэтому выбираем наиболее удобный вариант :3.

"vanya999" написал:
То есть идет наш указанный каталог, а дальше адрес может быть любым ?

Что?

#351783
XRevan86 написал:
[quote="yars"]про подкаталоги ни слова

Поэтому выбираем наиболее удобный вариант :3.

"vanya999" написал:
То есть идет наш указанный каталог, а дальше адрес может быть любым ?

Что?[/quote]
Ничего. Уже понял, что вы имели введу)

#351784

vanya999, дальше звездочка раскрывается в имена всех файлов и каталогов.

#351786
yars написал:
vanya999, дальше звездочка раскрывается в имена всех файлов и каталогов.

Зачем мы двойные кавычки ставим ? Я знаю, что это символ экранирования, но зачем они здесь нужны ?

#351788

vanya999
Двойные кавычки в отличие от одинарных не экранируют "$", кстати :).
Здесь они нужны для того, чтобы скрипт не ломался от пробелов в именах каталогов.

Войдите или зарегистрируйтесь, чтобы ответить.