Em vez do seguinte
printf '%s\t%s\t%s\t%s\n' 'index' 'podcast' 'website' 'YouTube'
Quero armazenar a saída do printf em uma variável Results, como posso fazer isso?
Em vez do seguinte
printf '%s\t%s\t%s\t%s\n' 'index' 'podcast' 'website' 'YouTube'
Quero armazenar a saída do printf em uma variável Results, como posso fazer isso?
Estou usando jq 1.7
Estou operando em info.json baixado por yt-dlp
yt-dlp --write-info-json --skip-download https://www.youtube.com/watch?v=vlIO-7Rpi7c
de
, en-US
e dentro de
, en-US
selecionar todos os objetos com elemento ext == vtt
.Isso funciona com sucesso da seguinte maneira :
jq 'pick(.subtitles | .de[],."en-US"[] | select (.ext == "vtt")) | del(..|nulls)' *.json
saída
{
"subtitles": {
"de": [
{
"ext": "vtt",
"url": "https://www.youtube.com/api/timedtext?v=vlIO-7Rpi7c&ei=JS05ZoT2Ftf0i9oP8dy4mAo&caps=asr&opi=112496729&xoaf=5&hl=en&ip=0.0.0.0&ipbits=0&expire=1715048341&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AB2ECEEABF48D1A16ADC7ACCB8A072D63EE12DCC.5F56904251766FB68624A68FF2BBB57B9CCFFD2F&key=yt8&lang=de&fmt=vtt",
"name": "German"
}
],
"en-US": [
{
"ext": "vtt",
"url": "https://www.youtube.com/api/timedtext?v=vlIO-7Rpi7c&ei=JS05ZoT2Ftf0i9oP8dy4mAo&caps=asr&opi=112496729&xoaf=5&hl=en&ip=0.0.0.0&ipbits=0&expire=1715048341&sparams=ip%2Cipbits%2Cexpire%2Cv%2Cei%2Ccaps%2Copi%2Cxoaf&signature=AB2ECEEABF48D1A16ADC7ACCB8A072D63EE12DCC.5F56904251766FB68624A68FF2BBB57B9CCFFD2F&key=yt8&lang=en-US&fmt=vtt",
"name": "English (United States)"
}
]
}
}
Para alguns vídeos do Youtube, o arquivo json não contém "en-US", mas contém "en", enquanto alguns contêm todos os três de, en, en-US. Então eu escrevi o seguinte
jq 'pick(.subtitles | .de[],.en[],."en-US"[] | select (.ext == "vtt")) | del(..|nulls)' *.json
jq: erro (em: 69): Não é possível iterar sobre nulo (nulo)
Como selecionar apenas .ext == "vtt" apenas para o idioma en,en-US,de se nem todos esses idiomas estiverem presentes no arquivo json?
Alguma sugestão? Eu li: Sequências de escape (Guia do usuário GNU Awk)
$ Filesystem='/dev/mapper/vgubuntu-Media'
$ FilesystemRegex="$(echo "${Filesystem}" | sed "s~/~\\\/~g")"
$ echo "$FilesystemRegex"
\/dev\/mapper\/vgubuntu-Media
$ df -H "${Filesystem}" | awk -v Regex="${FilesystemRegex}" '/$Regex/{print $5}'
awk: warning: escape sequence `\/' treated as plain `/'
$ df -H "${Filesystem}" | awk '/\/dev\/mapper\/vgubuntu-Media/{print $5}'
62%
sudo lsblk --fs -o NAME,FSTYPE,SIZE,FSSIZE,FSUSED,FSAVAIL,FSUSE%,MOUNTPOINTS,LABEL,PATH | grep -v '^loop'
NAME FSTYPE SIZE FSSIZE FSUSED FSAVAIL FSUSE% MOUNTPOINTS LABEL PATH
zram0 8G [SWAP] /dev/zram0
nvme0n1 1.8T /dev/nvme0n1
├─nvme0n1p1 ext4 768M /dev/nvme0n1p1
├─nvme0n1p2 ext4 768M 738.4M 240.9M 443.8M 33% /boot FedoraBoot /dev/nvme0n1p2
├─nvme0n1p3 ext4 768M UnassignedBoot /dev/nvme0n1p3
├─nvme0n1p4 vfat 128M 127.7M 22.4M 105.3M 18% /boot/efi EFI-SP /dev/nvme0n1p4
└─nvme0n1p5 LVM2_member 1.8T /dev/nvme0n1p5
├─vgubuntu-FedoraRoot ext4 100G 98.1G 47.9G 45.2G 49% / FedoraRoot /dev/mapper/vgubuntu-FedoraRoot
├─vgubuntu-FedoraSwap swap 32G [SWAP] /dev/mapper/vgubuntu-FedoraSwap
├─vgubuntu-UbuntuSwap swap 32G /dev/mapper/vgubuntu-UbuntuSwap
├─vgubuntu-UbuntuRoot ext4 50G /dev/mapper/vgubuntu-UbuntuRoot
├─vgubuntu-UbuntuHome ext4 18G /dev/mapper/vgubuntu-UbuntuHome
├─vgubuntu-FedoraHome ext4 18G 17.5G 6.5G 10.1G 37% /home FedoraHome /dev/mapper/vgubuntu-FedoraHome
├─vgubuntu-Data ext4 100G 98.1G 82G 11.6G 84% /mnt/Data Data /dev/mapper/vgubuntu-Data
├─vgubuntu-Documents ext4 250G 245G 208.5G 24G 85% /mnt/Documents Documents /dev/mapper/vgubuntu-Documents
├─vgubuntu-Media ext4 500G 491.1G 331.2G 134.8G 67% /mnt/Media Media /dev/mapper/vgubuntu-Media
└─vgubuntu-Backup ext4 100G 97.9G 9.1G 83.7G 9% /mnt/Backup Backup /dev/mapper/vgubuntu-Backup
Eu tenho um script (digamos Task.sh
) (com permissão executável):
Pseducódigo:
if [[ Not called from inside a script ]]; then
echo 'Not called from inside a script'
else
echo 'Called from a script'
fi
Eu tenho um script que diz Main.sh
(com permissão executável):
Value=$(Task.sh)
echo "${Value}"
$ Task.sh
Not called from inside a script
$ Main.sh
Called from a script
Por favor, sugira qual condicional colocar no pseudocódigo paraTask.sh
Um script gera saída de 3 linhas:
$ Filename /a/Resource/.Filename.man.markdown
.Filename.man.markdown
.Filename
man.markdown
Eu quero armazenar a saída de 3 linhas em uma variável separada, como posso fazer isso?
Filename /a/Resource/.Filename.man.markdown | IFS=$'\n' read -r File1 Filename1 Extension1
echo "$File1 $Filename1 $Extension1"
$ IFS=$'\n' read -r File1 Filename1 Extension1 < <(Filename /a/Resource/.Filename.man.markdown)
$ echo "$File1 $Filename1 $Extension1"
.Filename.man.markdown
Arquivo de teste:
cat Test.txt
#EXTM3U
#EXTINF:100
a.flac
#EXTINF:20
b.flac
resultado esperado
cat Test.txt
#EXTM3U
#EXTINF:100
#a.flac
#EXTINF:20
#b.flac
Experimento 1
sed -e '/^#EXTINF/a #' Test.txt
#EXTM3U
#EXTINF:100
#
a.flac
#EXTINF:20
#
b.flac
Meu experimento adiciona uma nova linha após anexar #
, não quero que essa nova linha seja adicionada.
Eu quero remover todos os caracteres até a primeira letra [a-zA-Z]
em uma string. Por exemplo:
#121Abc
-->Abc
%Ab#c
-->Ab#c
Ab#c
-->Ab#c
Abc
-->Abc
1Abc
-->Abc
1 21Abc
-->Abc
1^1 Abc
-->Abc
Nota: Todas as não letras incluem caracteres não imprimíveis.
É possível com ferramentas bash?
column
está disponível em pacotes util-linux
e bsdmainutils
. Ambos os pacotes estão instalados no Linux Mint 20.2
$ type column
column is /usr/bin/column
column is /bin/column
Ambas as colunas estão apontando para a ferramenta de coluna bsd. Como posso acessar a ferramenta de util-linux
?
Quando digito echo "${PATH}" | tr -s ':' '\n' | nl
de dentro de um script bash e no terminal recebo o mesmo resultado:
1 /home/nikhil/Documents/Git/Cs/Architecture/bin
2 /home/nikhil/.local/bin
3 /home/nikhil/opt/.nvm/versions/node/v16.13.0/bin
4 /home/nikhil/opt/bin
5 /usr/local/sbin
6 /usr/local/bin
7 /usr/sbin
8 /usr/bin
9 /sbin
10 /bin
11 /usr/games
12 /usr/local/games
13 /snap/bin
14 /home/linuxbrew/.linuxbrew/bin
15 /home/linuxbrew/.linuxbrew/sbin
16 /home/nikhil/.cargo/bin
17 /home/nikhil/.cabal/bin
18 /home/nikhil/opt/go/bin
19 /home/nikhil/.ruby/bin
20 /home/linuxbrew/.linuxbrew/opt/fzf/bin
Mas quando digito o seguinte dentro de um script bash e no terminal, recebo resultados diferentes:
# From Terminmal
$ type pandoc
pandoc is aliased to `/usr/bin/pandoc'
pandoc is /usr/bin/pandoc
pandoc is /home/linuxbrew/.linuxbrew/bin/pandoc
pandoc is /home/nikhil/.cabal/bin/pandoc
# From inside bash script
pandoc is /usr/bin/pandoc
Por que type
tem saída diferente de dentro do bashscript e do terminal? Como posso fazer com que a type
saída do script bash seja a mesma do terminal?
Eu fiz da seguinte forma:
$ gsettings get org.gnome.desktop.session idle-delay
uint32 300
$ gsettings set org.gnome.desktop.session idle-delay 80
$ gsettings get org.gnome.desktop.session idle-delay
uint32 80
Mas quando faço: dconf dump /org/gnome/
, vejo o seguinte:
$ dconf dump /org/gnome/desktop/session
[/]
idle-delay=uint32 60
Observação : dconf dump
mostra o valor real, mas gsettings
mostra um novo valor, mas é diferente do mostrado pelo dconf-editor
$ dconf dump /org/gnome/desktop/session
[/]
idle-delay=uint32 60
$ gsettings get org.gnome.desktop.session idle-delay
uint32 300
Observação : dconf dump
mostra o valor real, mas gsettings
mostra o valor padrão
Isso significa que gsettings
não estão funcionando no meu sistema? Se sim, como posso corrigir isso?
Eu tenho um script de shell que cria uma função (em um arquivo bashscript que é originado por .bashrc
) para cada arquivo Markdown para abri-lo no editor.
Exemplo:
ls /home/nikhil/Notes/Studies
Physics.md
Chemistry.md
Studies.md
index.md
ls /home/nikhil/Notes/Sports
Football.md
Cricket.md
index.md
Como você pode ver, algumas pastas (como Estudos) contêm um arquivo com o mesmo nome (Studies.md) e index.md, enquanto outras (como Sports) contêm index.md, mas não Sports.md
Agora, meu bashscript cria as seguintes funções
oPhysics(){ ${Editor:-vim} /home/nikhil/Notes/Studies/Physics.md }
oChemistry(){ ${Editor:-vim} /home/nikhil/Notes/Studies/Chemistry.md }
oStudies(){ ${Editor:-vim} /home/nikhil/Notes/Studies/Studies.md }
oiStudies(){ ${Editor:-vim} /home/nikhil/Notes/Studies/index.md }
oFootball(){ ${Editor:-vim} /home/nikhil/Notes/Sports/Football.md}
oCricket(){ ${Editor:-vim} /home/nikhil/Notes/Sports/Cricket.md}
oiSports(){ ${Editor:-vim} /home/nikhil/Notes/Sports/index.md}
Observe que: oStudies
e oiStudies
existem, enquanto apenas oiSports
existe.
Agora, como usuário, gostaria de digitar oStudies
or oSports
(isso falharia) e not oiSports
, e ele deve ser executado automaticamente oiSports
quando oSports
a função não existir. Isso ocorre porque, na maioria das vezes, o usuário está interessado em abrir os arquivos normais de markdown, e somente quando eles não existem, o usuário gostaria de abrir os arquivos index.md
. O usuário não lembra para qual pasta existe apenas index.md (por exemplo, pasta Sports).
Como posso fazer isso? O padrão que procuro é executar uma função oiBlahBlah
caso oBlahBlah
não exista, dado que oBlahBlah
é invocada pelo usuário.
Fazer alias não funcionará, pois não quero oStudies
executaroiStudies
Aqui está um código simplificado que imprime o nome do diretório se ele contiver um nome de arquivo com o mesmo nome do diretório pai e da .md
extensão.
FIND(){
find . -type d -exec sh -c '
for d do
[ -f "${d}/${d##*/}.md" ] && printf "%s\n" "$d"
done' find-sh {} +
}
FIND
Para generalizar, quero enviar o termo de pesquisa ${d}/${d##*/}.md
como argumento para a FIND
função, mas infelizmente isso não gera nada:
FIND(){
local SearchTerm="${1}"
find . -type d -exec sh -c '
for d do
[ -f "${SearchTerm}" ] && printf "%s\n" "$d"
done' find-sh {} +
}
FIND '${d}/${d##*/}.md'
Tenho certeza de que há algum problema com a cotação do SearchTerm
. Alguma dica?
Eu tentei: FIND '\${d}/\${d##*/}.md'
mas não tem saída
O trecho a seguir usa uma função personalizada HexNewLine que basicamente converte o hexdump e quebra no caractere 0x0a
$ echo -e "\t{
> "dependencies": {
> "prettier": {
> "version": "1.18.2",
> "from": "[email protected]",
> "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz"
> }
> }
> }" | HexNewLine
00000000 09 7b 0a '.{.'
0000000a 20 20 64 65 70 65 6e 64 65 6e 63 69 65 73 3a 20 ' dependencies: '
0000001a 7b 0a '{.'
0000001c 20 20 20 20 70 72 65 74 74 69 65 72 3a 20 7b 0a ' prettier: {.'
0000002c 20 20 20 20 20 20 76 65 72 73 69 6f 6e 3a 20 31 ' version: 1'
0000003c 2e 31 38 2e 32 2c 0a '.18.2,.'
00000043 20 20 20 20 20 20 66 72 6f 6d 3a 20 70 72 65 74 ' from: pret'
00000053 74 69 65 72 40 31 2e 31 38 2e 32 2c 0a '[email protected],.'
00000060 20 20 20 20 20 20 72 65 73 6f 6c 76 65 64 3a 20 ' resolved: '
00000070 68 74 74 70 73 3a 2f 2f 72 65 67 69 73 74 72 79 'https://registry'
00000080 2e 6e 70 6d 6a 73 2e 6f 72 67 2f 70 72 65 74 74 '.npmjs.org/prett'
00000090 69 65 72 2f 2d 2f 70 72 65 74 74 69 65 72 2d 31 'ier/-/prettier-1'
000000a0 2e 31 38 2e 32 2e 74 67 7a 0a '.18.2.tgz.'
000000aa 20 20 20 20 7d 0a ' }.'
000000b0 20 20 7d 0a ' }.'
000000b4 7d 0a '}.'
tr
para adicionar uma tabulação após o caractere de nova linha, mas nada acontece!$ echo -e "\t{
> "dependencies": {
> "prettier": {
> "version": "1.18.2",
> "from": "[email protected]",
> "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz"
> }
> }
> }" | tr '\n' '\n\t'
{
dependencies: {
prettier: {
version: 1.18.2,
from: [email protected],
resolved: https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz
}
}
}
Estou usando o Bash 4.4.20. Eu normalmente tenho a função main em cada bashscript. Se eu quiser originar este script de outra função dentro de outro script bash, isso entrará em conflito com a definição da função principal em ambos os scripts?
#A.sh
main() {
SomeFunction
}
SomeFunction(){
. B.sh
}
main "$@"
#B.sh
main(){
echo Hi
}
main "$@"
Existe alguma solução sem renomear a função principal?
Eu recebo um bashscript (Child) dentro de outro bashscript (Parent), em algum lugar no meio de Parent. O argumento passado para o Pai ao executá-lo é passado para o Filho. Como posso evitar esse comportamento? Não quero que os argumentos do pai sejam transferidos para o filho também.
NOTA : A analogia Pai Filho não é sobre o processo Pai Filho, mas sobre algo que vem antes do outro.
Além disso, eu queria ter o ambiente do Script pai (exceto os argumentos que são passados para ele) para o script de origem. Isso ocorre porque os valores padrão de argumento para os scripts são diferentes. Veja Exemplo Abaixo. O script pai usa algumas das funções definidas no script de origem e também o script de origem cria matrizes que estão sendo usadas pelo script pai. Além disso, preciso dos parâmetros posicionais do script pai, após a origem do script filho.
#!/usr/bin/env bash
# - goal: "Parent"
main() {
# # Path
#dScriptP="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
# # Argument
ParentArgument=${1:-40}
echo "ParentArgument=${ParentArgument}"
. Child.sh
}
main "$@"
#!/bin/false
# shellcheck shell=bash
# - goal: "Child"
main() {
# # Path
#dScriptP="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
# # Argument
ChildArgument=${1:-30}
echo "ChildArgument=${ChildArgument}"
}
main "$@"
$ ./Parent.sh 50
ParentArgument=50
ChildArgument=50
$ ./Parent.sh 50
ParentArgument=50
ChildArgument=30
$ find -name "Bik*"
./Biking
./Biking/Unsync/Biking.md.~6~
./Biking/Rendered/Biking.gen.html
./Biking/Biking.md
Agora, quando substituo a expressão por uma variável da seguinte forma:
$ a='-name "Bik*"'
$ find $a
Não recebo saída. Por que é tão? E o que deve ser modificado?
Eu quero encontrar todas as subpastas, que contém um arquivo markdown com o mesmo nome (e extensão .md
).
Por exemplo: Eu quero encontrar as seguintes subpastas:
Apple/Banana/Orange #Apple/Banana/Orange/Orange.md exists
Apple/Banana #Apple/Banana/Banana.md exists
Apple/Banana/Papaya #Apple/Banana/Papaya/Papaya.md exists
Alguma sugestão?
As soluções para o problema podem ser testadas usando o seguinte código:
#!/usr/bin/env bash
# - goal: "Test"
# - author: Nikhil Agarwal
# - date: Wednesday, August 07, 2019
# - status: P T' (P: Prototyping, T: Tested)
# - usage: ./Test.sh
# - include:
# 1.
# - refer:
# 1. [directory - Find only those folders that contain a File with the same name as the Folder - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/534190/find-only-those-folders-that-contain-a-file-with-the-same-name-as-the-folder)
# - formatting:
# shellcheck disable=
#clear
main() {
TestData
ExpectedOutput
TestFunction "${1:?"Please enter a test number, as the first argument, to be executed!"}"
}
TestFunction() {
echo "Test Function"
echo "============="
"Test${1}"
echo ""
}
Test1() {
echo "Description: Thor"
find . -type f -regextype egrep -regex '.*/([^/]+)/\1\.md$' | sort
echo "Observation: ${Green:=}Pass, but shows filepath instead of directory path${Normal:=}"
}
Test2() {
echo "Description: Kusalananda1"
find . -type d -exec sh -c '
dirpath=$1
set -- "$dirpath"/*.md
[ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]' sh {} \; -print | sort
echo "Observation: ${Red:=}Fails as it ignores B.md${Normal:=}"
}
Test3() {
echo "Description: Kusalananda2"
find . -type d -exec sh -c '
for dirpath do
set -- "$dirpath"/*.md
if [ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]
then
printf "%s\n" "$dirpath"
fi
done' sh {} + | sort
echo "Observation: ${Red:=}Fails as it ignores B.md${Normal:=}"
}
Test4() {
echo "Description: steeldriver1"
find . -type d -exec sh -c '[ -f "$1/${1##*/}.md" ]' find-sh {} \; -print | sort
echo "Observation: ${Green:=}Pass${Normal:=}"
}
Test5() {
echo "Description: steeldriver2"
find . -type d -exec sh -c '
for d do
[ -f "$d/${d##*/}.md" ] && printf "%s\n" "$d"
done' find-sh {} + | sort
echo "Observation: ${Green:=}Pass${Normal:=}"
}
Test6() {
echo "Description: Stéphane Chazelas"
find . -name '*.md' -print0 \
| gawk -v RS='\0' -F/ -v OFS=/ '
{filename = $NF; NF--
if ($(NF)".md" == filename) include[$0]
else exclude[$0]
}
END {for (i in include) if (!(i in exclude)) print i}'
echo "Observation: ${Red:=}Fails as it ignores B.md${Normal:=}"
}
Test7() {
echo "Description: Zach"
#shellcheck disable=2044
for fd in $(find . -type d); do
dir=${fd##*/}
if [ -f "${fd}/${dir}.md" ]; then
ls "${fd}/${dir}.md"
fi
done
echo "Observation: ${Green:=}Pass but shows filepath instead of directory${Normal:=}"
}
ExpectedOutput() {
echo "Expected Output"
echo "==============="
cat << EOT
./GeneratedTest/A
./GeneratedTest/A/AA
./GeneratedTest/B
./GeneratedTest/C/CC1
./GeneratedTest/C/CC2
EOT
}
TestData() {
rm -rf GeneratedTest
mkdir -p GeneratedTest/A/AA
touch GeneratedTest/index.md
touch GeneratedTest/A/A.md
touch GeneratedTest/A/AA/AA.md
mkdir -p GeneratedTest/B
touch GeneratedTest/B/B.md
touch GeneratedTest/B/index.md
mkdir -p GeneratedTest/C/CC1
touch GeneratedTest/C/index.md
touch GeneratedTest/C/CC1/CC1.md
mkdir -p GeneratedTest/C/CC2
touch GeneratedTest/C/CC2/CC2.md
mkdir -p GeneratedTest/C/CC3
touch GeneratedTest/C/CC3/CC.md
mkdir -p GeneratedTest/C/CC4
}
main "$@"
Eu quero passar o seguinte grupo de comandos bash
{ echo Apple; echo Banana; }
como um argumento para uma função bash definida da .bashrc
seguinte forma:
BashFunction(){
"$@" | SomeOtherFunction
}
BashFunction '{ echo Apple; echo Banana; }'
Mas recebo este erro:
{ echo Apple; echo Banana; }: command not found
Se eu remover as aspas da função bash
BashFunction(){
$@ | SomeOtherFunction
}
Então eu recebo esse erro
{: command not found
Por que o cron requer MTA para registro? Existe alguma vantagem especial nisso? Por que não pode criar um arquivo de log como a maioria dos outros utilitários?