2016-11-25 8 views
0

Я работаю над машиной Linux. У меня есть много файлов с таким же именем, со структурой каталогов, как это:Bash: как скопировать несколько файлов с одинаковым именем в несколько папок

P45_input_foo/result.dat 
P45_input_bar/result.dat 
P45_input_tar/result.dat 
P45_input_cool/result.dat ... 

трудно скопировать их один за другим. Я хочу, чтобы скопировать их в другую папку с именем, как data с похожими названиями папок и имен файлов:

/data/foo/result.dat 
/data/bar/result.dat 
/data/tar/result.dat 
/data/cool/result.dat ... 

В вместо копирования их один за другим, что я должен делать?

+1

Вы работаете на компьютере с Linux или Windows? Вам нужно решение 'bash' или' batch'? – Inian

+0

@ Inian Я работаю над машиной linux. Поэтому мне нужно решение bash. Спасибо, что напомнили мне –

ответ

1

Используя для цикла в Баш:

# we list every files following the pattern : ./<somedirname>/<any file> 
# if you want to specify a format for the folders, you could change it here 
# i.e. for your case you could write 'for f in P45*/*' to only match folders starting by P45 
for f in */* 
do 
    # we strip the path of the file from its filename 
    # i.e. 'P45_input_foo/result.dat' will become 'P45_input_foo' 
    newpath="${f%/*}" 

    # mkdir -p /data/${newpath##*_} will create our new data structure 
    # - /data/${newpath##*_} extract the last chain of character after a _, in our example, 'foo' 
    # - mkdir -p will recursively create our structure 
    # - cp "$f" "$_" will copy the file to our new directory. It will not launch if mkdir returns an error 
    mkdir -p /data/${newpath##*_} && cp "$f" "$_" 
done 

${newpath##*_} и ${f%/*} использования являются частью Bash методов обработки строк. Вы можете больше узнать об этом here.

+0

спасибо за ваш ответ, можете ли вы дать более подробную информацию? '{newpath ## * _}" кажется мне странным –

+0

Я не знаю, кто меня проголосовал. Можете ли вы помочь мне проголосовать? Я не дублировал свой вопрос. –

+0

@Lbj_x: я не спустил вас вниз, но кто бы это ни сделал, возможно, сделал это, потому что вы не показали нам никакого кода, который вы пытались решить вашу проблему. – Inian

1

Вам нужно будет извлечь 3-й пункт после того, как "_":

P45_input_foo -> Foo

создать каталог (если это необходимо) и скопировать файл на него. Что-то вроде этого (не проверял, может потребоваться редактирование):

STARTING_DIR="/" 
cd "$STARTING_DIR" 
VAR=$(ls -1) 
while read DIR; do 
    TARGET_DIR=$(echo "$DIR" | cut -d'_' -f3) 
    NEW_DIR="/data/$DIR" 
    if [ ! -d "$NEW_DIR" ]; then 
    mkdir "$NEW_DIR" 
    fi 
    cp "$DIR/result.dat" "$NEW_DIR/result.dat" 
    if [ $? -ne 0 ]; 
    echo "ERROR: encountered an error while copying" 
    fi 
done <<<"$VAR" 

Объяснение: предположении, что все пути вы упомянули, находятся под корень / (если не изменится STARTING_PATH соответственно). С помощью ls вы получаете список каталогов, сохраняете вывод в VAR. Передайте содержимое VAR в цикл while.

+0

Привет, возможно, я не объяснил это правильно. P45_ * - одна серия PXX_ * в одном каталоге. –

+0

@Lbj_x Извините. Я до сих пор не понимаю, что вы имеете в виду. Не могли бы вы привести пример? –

+0

в стартовом каталоге: у меня есть P45_input_ * серия папок. и P46_ * и P47_ * ect. Наверное, мне нужно сначала указать DIR в начале? –

1

Немного find и с несколькими трюками bash, приведенный ниже сценарий может сделать трюк для вас. Не забудьте запустить скрипт без mv и посмотреть, действительно ли "/data/"$folder"/" - это фактический путь, по которому вы хотите переместить файл (ы).

#!/bin/bash 

while IFS= read -r -d '' file 
do 

    fileNew="${file%/*}"  # Everything before the last '\' 
    fileNew="${fileNew#*/}" # Everything after the last '\' 

    IFS="_" read _ _ folder <<<"$fileNew" 

    mv -v "$file" "/data/"$folder"/" 

done < <(find . -type f -name "result.dat" -print0) 
+0

благодарю вас за ваши усилия –

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

  • Нет связанных вопросов^_^