2016-02-03 5 views
1

Я написал скрипт для изменения владельцев файлов на основе введенного списка ввода. Мой скрипт отлично работает в каталогах без пробелов в их имени. Однако он не может изменять файлы в каталогах с пространством в их имени. Я также хотел бы захватить вывод команды chown в файл. Может ли кто-нибудь помочь?Как захватить вывод chown в сценарии ksh

здесь мой сценарий в KSH:

#!/usr/bin/ksh 

newowner=eg27395 

dirname=/home/sas/sastest/ 
logfile=chowner.log 
date > $dir$logfile 
command="chown $newowner:$newowner"  
for fname in list 
do 
in="$dirname/$fname"      
if [[ -e $in ]]       
then 
    while read line 
    do 
      tmp=$(print "$line"|awk '{if (substr($2,1,1) == "/") print $2; if (substr($0,1,1) == "/") print '})   
      if [[ -e $tmp ]]                      
      then 
        eval $command \"$tmp\"           
      fi 
    done < $in 
else 
     echo "input file $fname is not present. Check file location in the script." 
fi 
done 
+0

Держу пари, что вам не нужен awk вообще: что находится в файле «Список»? –

+0

Файл списка и несколько других файлов ввода, которые могут быть добавлены в цикл for, содержат отчет о файлах, которые пользователи оставили. Я разделяю имена файлов с этими файлами, а затем пытаюсь изменить право собственности на них с текущим пользователем, чтобы можно было управлять диском. – Bijan

+0

Но ваша команда awk указывает, что в строке есть 2 поля. Что находится в этом файле? Это может быть источником ваших проблем. –

ответ

1

Eval лишают котировки на этой линии

command="chown $newowner:$newowner" 

Для того, чтобы получить линию для работы с пробелами вам нужно будет предоставить управляющие последовательности цитирует

command="chown \"$newowner:$newowner\"" 

Таким образом, команда, которая на самом деле работает Eval является

chown "$newowner:$newowner"  

Кроме того, вы, вероятно, нужно в кавычки этой переменной настройки, хотя вам необходимо настроить синтаксис

tmp="$(print "$line"|awk '{if (substr($2,1,1) == "/") print $2; if (substr($0,1,1) == "/") print '})" 

Для захвата вывода вы можете добавить 2> & 1> file.out где файл .out - это имя файла ..., чтобы заставить его работать с eval, когда вы его используете, вам нужно будет сбрасывать любые специальные символы так же, как вам нужно, чтобы обратная косая черта с двойными котировками

+0

Спасибо Джеймсу за ваши полезные комментарии. Я все еще не могу отправить вывод в выходной файл. Кажется, chown не любит выходной файл и отправляет все на экран. ls -l хотя работает #chown "$ newowner: $ newowner" "$ tmp" ls -l $ logfilepath fi done < $in >> $ logfilepath – Bijan

1

пара других ошибок:

  • date > $dir$logfile - не $dir переменная определена
  • безопасно считывать из файла: while IFS= read -r line

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

chmod "$newowner:$newowner" "$tmp" 
+0

Thanks Glen. Я упростил строку chown, как вы указали: chown «$ newowner: $ newowner» «$ tmp», но я не могу создать выходной файл, так как chown кажется не нравится выходной файл и отправляет все на экран. ls -l $ logfile >> $ output работает. – Bijan

+0

Есть ли сообщение об ошибке? –

+0

Ошибка синтаксиса, но ошибка разрешения. Так как у меня нет корневого преувеличения. После завершения сценария я передаю его администратору root для запуска – Bijan

1

Ваш пример кода предполагает, что список является «мета-файлом»: список файлов, в каждом из которых есть список файлов, подлежащих изменению. Когда у вас есть только один файл, вы можете удалить цикл while.
Когда список - это переменная с именами файлов, вам нужно echo "${list}"| while ....
Не совсем понятно, почему вы иногда хотите начать с третьего поля. Кажется, что иногда у вас есть 2 слова перед именем файла и хотите, чтобы их игнорировали. Вырезание строки на пробелах становится проблемой, когда ваши имена файлов также имеют пробелы. Решение ищет пространство, за которым следует косая черта: это пространство не является частью имени файла, и все до этого места можно удалить.

newowner=eg27395 

# The slash on the end is not really part of the dir name, doesn't matter for most commands 
dirname=/home/sas/sastest 
logfile=chowner.log 
# Add braces, quotes and change dir into dirname 
date > "${dirname}/${logfile}" 

# Line with command not needed 

# Is list an inputfile? It is streamed using "< list" at the end of while []; do .. done 
while IFS= read -r fname; do 
    in="${dirname}/${fname}" 
    # Quotes are important 
    if [[ -e "$in" ]]; then 
     # get the filenames with a sed construction, and give it to chmod with xargs 
     # The sed construction is made for the situation that in a line with a space followed by a slash 
     # the filename starts with the slash 
     # sed is with # to avoid escaping the slashes 
     # Do not redirect the output here but after the loop. 
     sed 's#.* /#/#' "${in}" | xargs chmod ${newowner}:${newowner} 
    else 
     echo "input file ${fname} is not present. Check file location in the script." 
    fi 
done <list>> "${dirname}/${logfile}" 
+0

Thanks Walter, очень полезные комментарии. Я не могу создать выходной файл, так как chown кажется не нравится выходной файл и отправляет все на экран. ls -l $ logfile >> $ output работает. То же самое можно сказать о том, как вы предложили перенаправление вывода в конце цикла, который я пробовал перед отправкой: done < list >> «$ {dirname}/$ {logfile}" – Bijan

+0

Я думаю, вы говорите об ошибках chown. Они записываются на консоль с помощью stderr. Stderr - это поток 2, stdout - поток 1. Вы можете сообщить команде написать stderr в том же месте, что и stdout с '2> & 1'. Убедитесь, что вы сначала перенаправляете stdout, поэтому используйте '>> '$ {dirname}/$ {logfile}" 2> & 1'. –

Смежные вопросы