2015-02-04 4 views
1

Я использую следующий код, чтобы настроить переменную, содержащую ряд разных имен файлов, после чего я потом буду выполнять некоторые функции. Используемые файлы находятся в другом каталоге (DIRECTORY) в каталоге, где выполняется код (CURRENT_DIRECTORY). Я подумал, что следующий код можно использовать для изменения в каталоге, содержащем файлы cd $DIRECTORY, сохранить список файлов в переменной $FILES, а затем вернуться в исходный каталог (cd $CURRENT_DIRECTORY), где остальная часть кода может быть выполнена. Однако, если я выполняю две команды эха, первый содержит список файлов, когда я вхожу в каталог, где хранятся файлы, но вторая команда эха просто печатает 'vclist_2d_*.txt', т. Е. Интерпретирует это как строку, а не список файлов (по-видимому, потому, что я вернулся к исходному каталогу и поэтому не может найти файлы, которые соответствуют vclist_2d_*.txt). Почему это происходит, и как я могу обойти эту проблему (без запуска всего в одном каталоге)?Установка переменных оболочки для хранения списков файлов

#!/bin/bash 
CURRENT_DIRECTORY=`pwd` 
DIRECTORY=/home/Documents/NewDirectory/ 

cd $DIRECTORY 
pwd 
FILES=vclist_2d_*.txt 
echo $FILES 
cd $CURRENT_DIRECTORY 
echo $FILES 

ответ

4

Необходимо сохранить результат расширения glob.

Глобусы не расширены в простых назначениях переменных, поэтому ваш текущий код расширяет glob, когда вы его используете echo (именно поэтому вы получаете поведение, которое видите). Попробуйте echo "$FILES", и он вообще не будет расширяться, например.

Назначение массивов, однако, развернуть так, чтобы FILES=(vclist_2d_*.txt) сразу разворачивал шарик, а затем с помощью echo "${FILES[@]}" позже будет работать правильно.

+0

Я собирался опубликовать ответ с 'FILES = $ (echo ...)', но мне больше нравится решение для вашего массива. – Barmar

+0

Не могли бы вы объяснить, почему нужен синтаксис 'echo '$ {FILES [@]}"? – 218

+0

Это расширение всех элементов в массиве. Как '' $ @ "', но для массива. К сожалению, я не вижу хороших краткий раздел в bashref об этом (что странно). –

1

FILES=vclist_2d_*.txt не распространяется на оболочку. FILES теперь содержит строку vclist_2d_*.txt.

echo $FILES отправляет echo vclist_2d_*.txt в оболочку. Затем оболочка расширяет шаблон, в результате получается либо A) строка vclist_2d_*.txt, если шаблон не соответствует ни одному, либо B) список совпадающих имен файлов.

Затем вы меняете каталог и повторяете процесс. Ни в коем случае не список файлов, назначенных для любой переменной.

Теперь вы могли назначить выход из echo vclist_2d_*.txt к переменной (SOMEVAR=$(echo vclist_2d_*.txt), но это было бы решить проблему только на полпути. Как вы намерены «действовать по каждому файлу в списке»? Если вы думать о for file in $SOMEVAR, что произойдет, если имя файла содержит пробел ...

самый простой, наиболее надежным решением для этого является использование find вместо:

find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} + 

В результате do_something передал список совпадающих файлов. Если список очень длинный, он может быть разделен на несколько вызовов do_something.

find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} \; 

Это приводит к do_something вызывается для каждого файла соответствия.

Если есть шанс, что ваш текущего каталог может содержать файлы, соответствующих шаблон переданного find выше, необходимо, чтобы избежать звездочки (добавляя кавычки, как я сделал, или избежать его через \*), чтобы избежать оболочек расширение превращает вашу команду find во что-то другое.

+0

Вы указали расширение в этих примерах. Никакой глобализации не делается, поэтому ваш последний абзац не нужен. Также у вас есть то, что '\;' и '+' делать назад. '\;' является единственным аргументом, а '+' является коалесцирующим. Использование массива отлично подходит для этого и позволяет использовать вещи, которые используют 'find' (и наоборот, используя' find', делает некоторые вещи проще, чем использование glob и массив). –

+0

@ EtanReisner: Отредактировано. – DevSolar

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