BASH Wildcard Expansion

3

Não tenho certeza de como expressar isso, e talvez seja por isso que não consigo encontrar nada, mas quero reutilizar os valores enumerados por um caractere curinga em um comando. Isso é possível?

Cenário:
$ ls /dir
1 2 3
O conteúdo de / dir são diretórios 1, 2 e 3.

$ cp /dir/*/file . Resulta no arquivo sendo copiado de / dir / 1 / dir / 2 e / dir / 3 para aqui.

O que eu gostaria de fazer é copiar os arquivos para um novo nome de destino com base na expansão de curingas.

$ cp /dir/*/file ???-file Resultaria no arquivo / dir / * / sendo copiado para 1 arquivo, 2 arquivos e 3 arquivos. O que eu não consigo descobrir é a porção ??? para dizer ao BASH que eu quero usar os valores expandidos do curinga.

Usando o curinga nas redes de destino, um erro de cp: cp: target '* -file' não é um diretório. Há algo mais no bash que pode ser usado aqui?

O comando de localização tem {} para usar com -exec , que é semelhante ao que estou procurando acima.

    
por Aaron Copley 11.01.2011 / 23:29

7 respostas

2
ls /dir |while read dirname; do cp -v /dir/"$dirname"/file "$dirname"-file ; done
    
por 12.01.2011 / 06:25
3

Meu primeiro pensamento é que você provavelmente está tornando este problema muito complicado. No entanto, é solucionável.

Você pode fazer algo assim com um loop bash maluco:

for i in /dir/*/file
do
  j=${i%/file}
  k=${j#/dir/}

  cp $i %k-file
done

que usa alguns operadores de string bash para extrair o número do diretório de origem.

Eu garanto que existem melhores maneiras de fazer isso, foi exatamente isso que me veio à mente.

    
por 12.01.2011 / 00:01
2
zsh% autoload zmv       # should be done for you, noting it just in case
zsh% zmv -C '(*)/file' '$1-file'

zmv é uma função do shell, geralmente usada via alias mmv='noglob zmv -W' para uma invocação ainda mais fácil, mas neste caso você quer o uso regular, além de -C copiar em vez de mover.

    
por 12.01.2011 / 01:19
0

Como Phil disse, você precisará iterar sobre os elementos do curinga expandido; extraindo o bit com o qual você se importa (no seu exemplo, o nome do diretório sob dir /) e, em seguida, atuando nesse valor extraído.

Eu tenho uma maneira diferente e rápida de fazer isso abaixo. O erro óbvio é que isso vai quebrar se houver espaços em nomes de arquivos, mas esse não é o único bug.

andromeda:tmp polleyj$ find dir/ ?-file
dir/
dir//1
dir//1/a
dir//1/b
dir//1/c
dir//2
dir//2/d
dir//2/e
dir//2/f
dir//3
dir//3/g
dir//3/h
dir//3/i
1-file
2-file
3-file
andromeda:tmp polleyj$ for f in dir/*; do
> i=$(basename $f)
> mv dir/${i}/* ${i}-file/
> done
andromeda:tmp polleyj$ find dir/ ?-file
dir/
dir//1
dir//2
dir//3
1-file
1-file/a
1-file/b
1-file/c
2-file
2-file/d
2-file/e
2-file/f
3-file
3-file/g
3-file/h
3-file/i
andromeda:tmp polleyj$ 
    
por 12.01.2011 / 00:24
0

Na maioria das distros (usando o renomear ) do util-linux:

rename /file -file /dir/*/file

No Debian e no Ubuntu (culpe o Debian):

rename.ul /file -file /dir/*/file

Ou usando a renomeação do Perl (no Debian e no Ubuntu, não sei onde encontrá-lo em outras distros):

rename 's,(\d+)/file,$1-file,' */file
    
por 12.01.2011 / 00:48
0

Não é bonito:

find -type f -exec sh -c 'cp "{}" "$(basename "$(dirname "{}")")-$(basename "{}")"' \;
    
por 12.01.2011 / 06:09
0

Se eu entendi, o mcp está fazendo o que você quer.

Dica: o mcp pertence ao pacote mmv .

Sua situação:

$ tree
.
├── dir
│   ├── 1
│   │   └── foo
│   ├── 2
│   │   └── bar
│   └── 3
│       └── baz
└── dst

5 directories, 3 files

A solução:

$ mcp -v 'dir/*/*' 'dst/#1-#2'
dir/1/foo -> dst/1-foo : done
dir/2/bar -> dst/2-bar : done
dir/3/baz -> dst/3-baz : done

$ tree
.
├── dir
│   ├── 1
│   │   └── foo
│   ├── 2
│   │   └── bar
│   └── 3
│       └── baz
└── dst
    ├── 1-foo
    ├── 2-bar
    └── 3-baz

5 directories, 6 files

Eu acho que deve ser mais auto-explicativo

O que acontece aqui é que o mcp leva um de e um argumento para . O argumento de pode conter padrões de caractere curinga de shell (* ,?) que correspondem a um conjunto de arquivos. Essas correspondências são referenciadas novamente no padrão para de forma ordenada como # 1, # 2, # 3 e assim por diante.

    
por 13.01.2011 / 15:07

Tags