Как запустить один и тот же код в нескольких файлах или во всех файлах в каталоге

так что я очень новичок в программировании и недавно написал небольшую программу, в которой использовались R и sox. Это выглядело так

file <- "test.mp3"

testSox = paste("sox ",file," -n spectrogram -o ",file,".png stats",sep='')
sox = system(testSox, intern = TRUE)
print(sox)

Теперь вместо того, чтобы назначать один файл вручную в коде, я просто хотел бы, чтобы этот код автоматически читал все mp3 в папке. Это возможно? Любая помощь будет принята с благодарностью. Спасибо!

РЕДАКТИРОВАТЬ: На самом деле, я должен добавить, что я пробовал list.files, но когда дело доходит до запуска команды system(), я получаю

«Ошибка в системе (команда, as.integer (флаг), f, stdout, stderr): строка символов ожидается в качестве первого аргумента»

Вот код list.files, который я пробовал:

> temp = list.files(path = ".", pattern=".mp3")
> 
> file <- temp
> 
> firstSox = paste("sox ",file," -n spectrogram -o ",file,".png stats",sep='')
> sox = system(firstSox, intern = TRUE)
Error in system(command, as.integer(flag), f, stdout, stderr) : 
  character string expected as first argument
> print(sox)

Я предполагаю, что это не правильный путь? Потому что мне в основном нужно заменить «файл» в строке firstSox на каждый mp3, который находится в массиве temp. Итак, вместо запуска:

file <- "test.mp3"

... Я просто хотел бы, чтобы он каждый раз переназначался для каждого файла в папке..., чтобы он выполнялся как test.mp3, затем 1.mp3, затем 2.mp3 , затем 3.мп и т.д.

Я обыскал сеть и просто чувствую, что наткнулся на кирпичную стену. Как указано в комментариях, я читал о циклах, но по какой-то причине я не могу понять, как включить его в то, что я написал. Я чувствую, что мне просто нужно, чтобы кто-то показал мне хотя бы путь или, может быть, даже написал мне пример, чтобы я мог обдумать его. Буду очень признателен за помощь и любые советы о том, что я делаю неправильно и могу исправить. Спасибо.


person TwinSpiritRadio    schedule 19.05.2014    source источник
comment
Вам может быть интересно прочитать stackoverflow.com/questions/9564489/   -  person talat    schedule 19.05.2014
comment
Спасибо, beginneR, я проверю эту страницу как можно скорее.   -  person TwinSpiritRadio    schedule 19.05.2014
comment
Вы когда-нибудь сталкивались с программной концепцией цикла? Потому что это может пригодиться здесь.   -  person joran    schedule 20.05.2014
comment
Да, но я еще не включил его в какой-либо собственный код. Как я уже сказал, я новенький :-). Я читал о циклах, но чувствую себя идиотом, потому что не знаю, как включить это в свой код. На самом деле это только часть кода, который я написал, и все это работает для одного файла. Мне просто нужно обдумать, как заставить его работать со всей папкой файлов, кроме одного.   -  person TwinSpiritRadio    schedule 20.05.2014


Ответы (2)


Попробуйте приведенный ниже код. Я использую dir() вместо list.files просто потому, что мне так проще. Помните, что есть много способов сделать то же самое в R.

files <- dir(path = ".",pattern = ".mp3") #Get all the mp3 files

for(f in files) {     #Loop over the mp3 files one at a time

    firstSox = paste("sox ",f," -n spectrogram -o ",f,".png stats",sep='')
    sox = system(firstSox, intern = TRUE)
    print(sox)

}
person Rohit Das    schedule 19.05.2014
comment
Рохит, это сработало прекрасно! Я добавил остальную часть своего кода, и все работает, кроме одного. У меня есть уведомления stop() в исходном коде, потому что я не хотел, чтобы определенные mp3-файлы проходили через всю программу. Есть ли другая команда, кроме stop(), которая могла бы просто остановить цикл, если дойдет до определенного оператора if, а затем перезапустить цикл со следующим mp3? - person TwinSpiritRadio; 20.05.2014
comment
Добро пожаловать. Я уверен, что вы уже поняли это, но загляните в next cran.r-project.org/doc/manuals/r-release/R-lang.html#Looping. У меня возник соблазн дать ответ, используя одну из функций применения, но, учитывая, что вы только начинаете, цикл for легче визуализировать. Но обязательно рассмотрите решение, предоставленное Грегом Сноу, поскольку оно позволит вам писать гораздо более эффективный код. - person Rohit Das; 30.05.2014

Ваша переменная firstSox будет вектором команд для запуска (paste сгенерирует вектор, по одной строке для каждого элемента file). Так что теперь вам просто нужно запускать каждую команду через system

Один из способов сделать это и получить вывод — использовать функцию lapply или sapply:

sox <- lapply( firstSox, function(x) system(x, intern=TRUE) )

В этом коде lapply будет запускать функцию для каждого элемента firstSox по одному, функция просто берет текущий элемент (в x) и передает его системе. Затем lapply собирает все выходные данные вместе и объединяет их в список, который помещает в sox.

Если результаты каждого прогона дают одинаковую форму результатов (одиночное число или вектор одинаковой длины), вы можете использовать вместо этого sapply, и это упростит возврат в вектор или матрицу.

person Greg Snow    schedule 19.05.2014
comment
Спасибо, Грег, это отлично работает для запуска кода наверху, хотя у меня гораздо больше кода, работающего в файле, поэтому цикл for, который предоставил Рохит, больше подходит для моей общей ситуации. Но спасибо за подсказку! - person TwinSpiritRadio; 20.05.2014
comment
@TwinSpiritRadio, вы можете написать функцию, которая будет делать всю работу, которую вы хотите, а затем передать эту функцию sapply. В общем, если вы заботитесь только о побочных эффектах, тогда подойдет цикл for, но если вы хотите сохранить выходные данные каждой итерации, то в долгосрочной перспективе lapply и sapply, как правило, будут лучше. - person Greg Snow; 20.05.2014
comment
Спасибо, Грег. Я собираюсь применить его к своему коду так, как вы только что описали, и посмотреть, что работает лучше всего. Очень ценю советы! - person TwinSpiritRadio; 21.05.2014