Quero renomear arquivos para alterar sua extensão, procurando efetivamente realizar
mv *.txt *.tsv
Mas ao fazer isso, recebo:
* .tsv não é um diretório
Acho um pouco estranho que os 10 primeiros hits do google mvfuncionem assim.
Quero renomear arquivos para alterar sua extensão, procurando efetivamente realizar
mv *.txt *.tsv
Mas ao fazer isso, recebo:
* .tsv não é um diretório
Acho um pouco estranho que os 10 primeiros hits do google mvfuncionem assim.
Respostas:
Quando você emite o comando:
mv *.txt *.tsv
o shell, vamos assumir o bash, expande os curingas se houver algum arquivo correspondente (incluindo diretórios). A lista de arquivos é passada para o programa, aqui mv. Se nenhuma correspondência for encontrada, a versão não expandida será aprovada.
Novamente: o shell expande os padrões, não o programa.
Cargas de exemplos é talvez a melhor maneira, então vamos lá:
$ ls
file1.txt file2.txt
$ mv *.txt *.tsv
Agora, o que acontece na mvlinha é que o shell se expande *.txtpara os arquivos correspondentes. Como não há *.tsvarquivos que não são alterados.
O mvcomando é chamado com dois argumentos especiais :
argc: Número de argumentos, incluindo o programa.argv: Uma matriz de argumentos, incluindo o programa como primeira entrada.No exemplo acima, isso seria:
argc = 4
argv[0] = mv
argv[1] = file1.txt
argv[2] = file2.txt
argv[3] = *.tsv
O mvprograma verifica se o último argumento,, *.tsvé um diretório. Como não é, o programa não pode continuar, pois não foi projetado para concatenar arquivos. (Normalmente, mova todos os arquivos para um.) Nem crie diretórios por capricho.
Como resultado, ele interrompe e relata o erro:
mv: target ‘*.tsv’ is not a directory
Agora, se você diz:
$ mv *1.txt *.tsv
O mvcomando é executado com:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv
Agora, novamente, mvverifique se *.tsvexiste. Como não, o arquivo file1.txté movido para *.tsv. Ou seja: o arquivo é renomeado para *.tsvcom o asterisco e tudo.
$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’
$ ls
file2.txt *.tsv
Se você disse:
$ mkdir *.tsv
$ mv *.txt *.tsv
O mvcomando é executado com:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[1] = file2.txt
argv[2] = *.tsv
Como *.tsvagora é um diretório, os arquivos acabam sendo movidos para lá.
Agora: usando comandos como some_command *.tsvquando a intenção é realmente manter o curinga, deve-se sempre citá-lo. Ao citar, você evita que os curingas sejam expandidos se houver correspondências. Por exemplo, digamos mkdir "*.tsv".
A expansão pode ser vista ainda mais se você fizer, por exemplo:
$ ls
file1.txt file2.txt
$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists
Agora: o mvcomando pode e funciona em vários arquivos. Mas se houver mais de dois, o último terá que ser um diretório de destino. (Opcionalmente, você pode usar a -t TARGET_DIRopção, pelo menos para GNU mv.)
Então, tudo bem:
$ ls -F
b1.tsv b2.tsv f1.txt f2.txt f3.txt foo/
$ mv *.txt *.tsv foo
Aqui mvseria chamado com:
argc = 7
argv[0] = mv
argv[1] = b1.tsv
argv[2] = b2.tsv
argv[3] = f1.txt
argv[4] = f2.txt
argv[5] = f3.txt
argv[6] = foo
e todos os arquivos acabam no diretório foo.
Quanto aos seus links. Você forneceu um (em um comentário), onde mvnão é mencionado, mas rename. Se você tiver mais links, poderá compartilhar. Assim como nas páginas de manual em que você afirma que isso é expresso.
Sei que isso não responde à sua pergunta, mas, se você estava procurando outra maneira de renomear os arquivos em comparação com o loop da solução alternativa, por que não usar find? Eu usei esse comando várias vezes para substituir as extensões de arquivos em grandes diretórios por centenas de milhares de arquivos. Isso deve funcionar em qualquer sistema compatível com POSIX:
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
Divisão de comando:
'
.' => caminho de pesquisa começando no diretório atual marcado por '. "
-name=> define o nome da correspondência de localização (nesse caso, todos os arquivos que terminam com.gappedPeak)
-exec=> execute o seguinte comando em cada partida
sh -c=> 'exec' cria um ambiente de shell independente para cada correspondência
mv "$1" "${1%.gappedPeak}.bed"=>mvprimeira variável (indicada por $ 1 ), que é o nome do arquivo atual, com o novo nome. Aqui eu faço uma correspondência de substring e apago; então pegue o primeiro var novamente, $ 1 e use%para excluir.gappedPeakda string. A.bedno final apenas encadeia a variável remanescente, que é agora apenas , com , criando o novo nome de ficheiro.test#.bedtest#.bedO sublinhado é um espaço reservado por US $ 0
O
{}é substituído por cada*.gappedPeaknome de arquivo ( ) encontrado pelofindcomando e se torna $ 1 noshcomando.
\;marca o final do-execcomando. Você também pode usar';'ou";".
Exemplo:
[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak
[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed
file.abc-> blub.xyzem vários sub dirs:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
mv *.txt *.tsvnão funciona; mvpode renomear apenas um arquivo por vez. Você entendeu mal as explicações ou elas estão erradas.
mmve renamepode renomear vários arquivos de uma vez. Mas existem duas versões em renametorno das quais são chamadas de maneira diferente. Deve haver muitas perguntas sobre isso aqui.
rename, não mv.
mv *.txt *.tsv mv(geralmente) não vê *.txtou *.tsvos nomes de arquivo expandidos pelo shell. O número de arquivos para os quais esses curingas se expandem seria "aleatório". A única situação em que isso funciona é se houver um arquivo com o nome *.txtque será renomeado para (literalmente) *.tsv(sem citar a bashopção nullglobnão deve ser configurada).
foo.txte um chamado baz.tsva mv *.txt *.tsvirá substituir o existente .tsvarquivo ...
Por exemplo, se você tem asd.txte qwe.txtarquivos no diretório ao executar o comando mv *.txt *.tsv, ele tenta mover esses dois arquivos para um diretório chamado *.tsv. Como não existe esse diretório, ocorre um erro.
rename(1)renameé um script perl de Larry Wall, o criador do perl. Ele usa um regex Perl e opera no nome do arquivo.
rename 's/\.txt$/.tsv/' *.txt
Se você precisar instalar renameno Debian / Ubuntu, poderá fazer
sudo apt install rename
Outra opção a considerar é usar:
cp -p *.txt *.tsv
rm -f *.txt
*.txtarquivos para *.tsvpreservar seus atributos usando o -psinalizador.*.txtmvque simplesmente altera o / directory / filename sem realmente mover os arquivos, a menos que estejam em uma partição diferente.