Newsgroup: it.comp.os.linux.iniziare
Titolo: abbreviare un path togliendo i tre segmenti iniziali

/a/b/c/d/e/f
 
voglio abbreviarlo in
 
d/e/f
 
senza usare regex, splitters, array, complicazioni varie, ecc.
 
Esiste quindi un comando tipo
 
comando-che-non-so /a/b/c/d/e/f 3 # rimuove i primi tre segmenti
comando-che-non-so /a/b/c/d/e/f 4 # rimuove i primi quattro segmenti
...
 
Esiste?

 Esiste?
 
In prima battuta ti avrei risposto con basename. Di fatto però non lo fa.
Pertanto, ti suggerisco quello che mi ha suggerito l'internet:
 
### Inizio script bash
#!/bin/bash
 
IFS=/ read -a a <<< "$1"
IFS=/ scratch="${a[*]:${#a[@]}-$2}"
echo "$scratch"
### Fine script bash
 
Ovviamente una cosa del genere la fai con qualunque linguaggio, e.g. questa è
una versione in python:
 
###
import sys
 
arg = sys.argv[1]
size = int(sys.argv[2])
 
scratch = arg.split("/")
basename = scratch[len(scratch) - size:]
print("/".join(basename))
###
 
Insomma, non hai una soluzione unica ma hai parecchi strumenti per farla
 
Enrico

Addi' 06 giu 2019 09:07:13, alex scrive:

Anche Enrico dice di no, comunque ti conviene dire dove (login o no) e
quando e perche' e come lo vuoi cambiare.
Per dire: magari vuoi escludere i local/ e allora puoi usare "grep -v".
In ogni caso il separatore e' ":", non "/".
 
Guarda quest'altra in aggiunta a quelle di Enrico, se ti piace. Pero'
se devi cambiarlo alla shell di login devi darlo con source (o col
punto) ciao
 
-=-=-=-=-=- cut here =-=-=-=-=-
#!/bin/bash
 
PATH=$(echo "$PATH" \
| awk -vUNO="$1" -F: '{ORS=":" ; for (j=UNO; j<=NF; j++) print $j}' \
| sed 's/:$/\n/')
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
Usage:
$: comando-che-non-so 3     ...per la shell di non-login
$: . comando-che-non-so 3   ...per quella di login
 
 
Postilla. Ma un esperto di awk (BIG UMBERTO ci sei?) te lo riduce
certamente, togliendo almeno il sed ariciao
 
-- 
Yoda
 

 ...
 
Mi sa che mi faccio uno scriptino in php.
Naturalmente ho dedotto che la risposta alla mia domanda è NO: il 
problema semplicissimmo richiede una soluzione complicatissima :)

 certamente, togliendo almeno il sed ariciao
 
 
A parte che l'OP ha gettato la spugna, e non aveva detto in che ambito gli
serviva l'aiuto, ti posso rispondere che la soluzione l'avevi in mano.!
 
 
V come variabile nell'esempio è il path che vorrebbe l'OP sezionare.
 
 
 
comando-che-non-so   NumeroCampiDaEscludere
 
-----[CUT]---------
#!/bin/bash
# Stampa i caratteri DOPO la ricorrenza N di un carattere, la  "/" in questo esempio
# Stampa il PATH esclusi i $1 primi elementi
 
V="a/b/c/d/e/f/g"
 
echo "stringa =  $V "
 
echo "$V" |\
awk -vU="$1" '{R = 1 ; split ($0, a, "")
for (j=0; j<=length($0); j++) {
if (a[j] == "/") R = R + 1
if ( R >= U ) printf "%s", a[j] }
{print "\n"} }'
-----[CUT]---------
 
 
Divisa su più righe *SOLO* per leggibilità ed impaginazione.
 
La variabile U è la ricorrenza del carattere "/" barra cercato.
 
Nota che la variabile R usata per contare, comincia da 1 perchè il primo
carattere della stringa NON contiene il separatore "/" barra!
 
Nel caso invece la stringa iniziasse con "/", R deve essere inizializzato con 0
(volendo si può aggiungere un test).
 
Per $1 > separatori "/" della stringa, stampa stringa vuota!
 
 
 
-- 
Ieri ho comprato un cartone animato a mio figlio, ma era doppiato male...
Invece di dire "alabarda spaziale" e "maglio perforante", Goldrake diceva
"brotola speziata" e "maglioncino trapuntato"....

 -----[CUT]---------
 
 
Orco! Saltata una riga nel copia-incolla:
 
echo "$V" |\
awk -vU="$1" '{R = 1 ; split ($0, a, "")
for (j=0; j<=length($0); j++) {
if (a[j] == "/") R = R + 1
if (a[j] == "/" && R == U ) { R++ ; j++ }
if ( R >= U ) printf "%s", a[j] }
{print "\n"} }'
 
 
 
 


 A parte che l'OP ha gettato la spugna
 
??????
BOHHH :D
 
Cmq ti ringrazio per la soluzione, anche se avrei voluto che linux 
avesse un comando ad hoc.
Ad ogni modo per me la semplicità, la pulizia, e la leggibilità del 
codice, contano molto (bash non aggevola molto questo aspetto), per cui 
ho ripiegato su php:
 
// usage: left-splice SEGMENTS PATH
$pathArray = split($arg[2], DIRECTORY_SEPARATOR);
$path      = array_splice($pathArray, 0, $arg[1]);
$ltrimPath = ltrim($path, DIRECTORY_SEPARATOR);
echo $ltrimPath;
 
Un po' eglio direi :)

 {print "\n"} }'
 
NF, NF... e -F...
 
echo $V | gawk -vU=... -F'/' '{...}'
 
qualcosa=U-1
for(i=NF-qualcosa;i++;i<NF)
  printf("%s/",$i)
print $NF
 
Naturalmente, usare '/' potrebbe non essere
corretto, magari c'e` una variabile.
Secondo, si deve controllare che il loop
funzioni, cioe` che "NF-qualcosa>=0".
 
bye,
 
-- 
 
piergiorgio


Dipende.
 
Se quel codice deve girare su un sistema _senza_ php
non e` una buona soluzione.
 
Installare php solo per quel codice puo` non essere
una cosa desiderabile.
 
Mentre bash, gawk e simili hanno piu` probabilita` di
essere presenti su svariati sistemi Unix.
 
Quindi, dipende...
 
bye,
 
-- 
 
piergiorgio

 -----[CUT]---------
 
Cavoli! vedo che ho capito tutto sbagliato, io pensavo che Alex volesse
cambiare il PATH, non un generico path - assoluto tra l'altro.
 
Ora mi gusto il tuo con awk (imparare senza soffrire! ;-)) facendo
l'eseguibile, perche' cosi' a mente ci capisco poco.
 
Pero', visto che e' col path assoluto, vedo gia' una soluzione fulminea,
anche da riga di comando:
 
$: echo a/b/c/s/e/f/g | sed "s#/# #$1" | awk '{print $2}'
 
Ciao e grazie per l'awk
 
-- 
Yoda
 

 funzioni, cioe` che "NF-qualcosa>=0".
 
 
Beh!
L'OP voleva la parte dopo N path e non gli ultimi N path....
 
echo "$V" |\
awk -vU=$1 -F'/' '{
for(i=(U+1);i<NF;i++)
  printf("%s/",$i)
print $NF }'
 
Più semplice.
Ci avevo pensato già io, era la prima soluzione ovvia.
Mi ero impantanato con l'ultimo campo.
 
Bastava mettere il contatore i<NF e stampare NF alla fine, come hai fatto tu.
 
Ti ho solo rigirato gli indici per fare da "ultimi N campi" a "tranne i primi N
campi".
 
-- 
Elon Musk: ''La vostra Tesla vi seguirà come un cagnolino''  ( 03 Nov 2018 )
Quindi ora per rubare una Tesla non serve nemmeno di andargli vicino, si può
fare direttamente dal divano. Comodo!

Il 06/06/19 11:07, alex ha scritto:

[alessandro@wkstn05 ~]$ A='/a/b/c/d/e/f'
[alessandro@wkstn05 ~]$ echo ${A#/?*/?*/?*/}
d/e/f
[alessandro@wkstn05 ~]$
 
 
  Ciao,
 
 
Alessandro
 

>>>>  
http://www.bb2002.it
 :)  <<<<<
........... [ al lavoro ] ...........

 [alessandro@wkstn05 ~]$
 
Strano come Slrn non interpreti giusto il tuo header
Content-Type: multipart/signed; blablabla
come si vede dal quotato qui su, specie per le tre righe tue.
 
Comunue l'ho salvato e dato in pasto ad ascii2uni:
$: ascii2uni -qa I < intossicato | grep -A1 n05
 
ottenendo:
--------------
[alessandro@wkstn05 ~]$ A='/a/b/c/d/e/f'
[alessandro@wkstn05 ~]$ echo ${A#/?*/?*/?*/}
d/e/f
[alessandro@wkstn05 ~]$
 
--------
 
Questa tua soluzione e' certo la piu' breve, ma va solo come riga di
comando ed inoltre ti tocca ripetere i "/?*" per il numero di volte
che scegli.
Ho capito che il "?" serve per evitare gli eventuali "//", ed allora
ho capito anche che la mia:
echo /ab/c/e/f/g | sed 's#/# #$1' | awk '{print $2}'
 
fallisce se ci sono directory intossicate (con spazi), si dovrebbe
cambiare con ad esempio:
echo "$1" | sed "s#/#ZZZZZZ#$2" | awk -FZZZZZZ '{print $2}'
 
ovvero da riga di comando:
echo /a/b/c/e/f/g | sed 's#/#ZZZZZZ#3' | awk -FZZZZZZ '{print $2}'
 
Ciao
 
-- 
Yoda
 

 campi".
 
Ottimo!
Come sempre test / debugging da punti di vista
diversi e` efficace!
 
bye,
 
-- 
 
piergiorgio

 Quindi, dipende...
 
Un sistema senza php, c, python, ormai viene considerato un po' 
*indegno* di esistere :D

 $: echo a/b/c/s/e/f/g | sed "s#/# #$1" | awk '{print $2}'
 
Un po scomodo da ricordare/digitare :D

 *indegno* di esistere :D
 
Senza Python potrei capire ci sia un problema, ma gli
altri due sono benissimo (e devono esserlo) evitabili.
 
Sono sicuro che la cosa si sarebbe potuta fare con una
sola riga del leggibilissimo Java, ma magari installare
un JVM per estrarre un path pare un po' eccessivo.
 
Infine, riguardo il fatto "che non esista un programma
Unix gia` fatto", quando si ha un problema del genere e
non esiste una soluzione precotta, bisogna *sempre*
chiedersi se il problema sia proprio un caso particolare
che non si puo` evitare, oppure ci si sia posti la cosa
nel modo sbagliato.
 
Come al solito, tu _non_ hai spiegato *perche`* ti serve
fare quello split.
 
E` molto probabile che tutto il problema, incluso il php,
siano irrilevanti, se considerati da un punto di vista
diverso, cioe` da come si e` arrivati a voler fare quella
separazione del path.
 
bye,
 
-- 
 
piergiorgio

 Un po scomodo da ricordare/digitare :D
 
L'ho riscritta rispondendo ad Alessandro, devi fare uno script
cutpath cosi':
------------------
#! /bin/bash
 
if [ -z "$1" ]; then
echo '
Dare il path in $1 e in numero da cui partire in $2
esempio_1:
$: cutpath /pippo/pluto/paperino/boh/ 3
 
esempio_2:
$: cutpath `cat /tmp/miopath` 6
'
exit 0
fi
 
echo "$1" | sed "s#/#ZZZZZZ#$2" | awk -FZZZZZZ '{print $2}'
------------------------
 
e vedrai che difficilmente lo fai piu' velocemente ciao
 
-- 
Yoda
 

= C ) { printf "%s", $I FS }}}'
 
  Riconosco sia una scrittura più complessa, ma nel mio sistema impiega
ben il 3,7% di tempo in meno! :-P
 
 
  Ciao,
 
 
Alessandro
 

 exit 0
 
Forse è meglio un exit 1, soprattutto se lo script viene richiamato da 
un altro script e per eventuale debug (set -ex).

 fare quello split.
 
Ho un software casareccio per gestire repositories locali a cui attinge 
composer.
Il software accetta solo percorsi relativi.
 
alias arb
admin-repo backup
 
$ pwd
/a/qesto/quello/b/c/quellaltro/d/e/f
$ arb d/e/f
 
Siccome a volte mi annoio a fare il cutting manuale, faccio
 
$ my-php-cut 6 $(pwd)
 
e ottengo subito
 
d/e/f
 
a cui antepongo
 
arb
 

 
]zac[
 
echo '/a/b/c/d/e/f' | cut -d '/' -f 5-
 
d/e/f
 
 

 arb
 
E non sarebbe meglio cambiare il "software casareccio"
in modo da accettare qualunque tipo di path?
 
Senza contare che non si capisce esattamente come sia
possibile avere un SW che capisca i path relativi e
non quelli assoluti...
 
bye,
 
-- 
 
piergiorgio

 non quelli assoluti...
 
Il path relativo funge anche da map-index per costruire (mappare) il 
full-path di backup di destinazione (collocato su apposito nas casalingo).
Insomma roba da rivedere a suo tempo.
 
Comunque diciamo che più che un path è un identificativo.
Hai presente composer?
 
$ composer require php/unit
 
scarica un pacchetto il cui real-full-path dovrebbe essere qualcosa del tipo
 
https://github.com/PERCORSO/SEGRETO/ASSOLUTO/ACCOUNTS/php/unit
 
 
Non va certo a cercare la directory php/unit sul mio computer :)


buono a sapersi

 No, funziona anche negli script bash.
 
Allora un bel grazie se mi dici come faccio a dare da script:
for j in {$1..$2}; do
 
io mi sono arreso e ho messo seq:
for j in $(seq $1 $2); do
 
ma adesso non ricordo perche' avrei preferito molto di piu' le graffe.
 
P.S. Hai visto Giuseppe con cut?! ciao
 
-- 
Yoda
 

Addi' 08 giu 2019 14:14:43, Giuseppe Della Bianca scrive:

!! splendida sorpresa!
 
E si possono risparmiare anche spazi e quote:
echo /a/b/c/d/e/f | cut -d/ -f5-
 
-- 
Yoda
 

 Web 0.6.
 
Bah.. sara' certamente cosi', pero' tieni presente che da te il
Thunderbird ti fa queste due cose che non mi sembrano regolari:
 
1. lascia una riga in bianco negli header, ed e' per questo che tutto
quello che c'e'dopo (e che c'e' qui su quotato) non viene piu'
interpretato come header, ma come corpo dell'articolo;
 
2. queste tre righe:
---------
Content-Type: text/plain; charset=iso-8859-15
Content-Language: en-US
Content-Transfer-Encoding: quoted-printable
-----
dovrebbero /precedere/ il primo Content-Type dell'header, subito dopo il
Mime-Version, solo cosi' si traduce giusto il quoted-printable.
 
Vedi, adesso ho fatto a manina queste due cose nel file tuo (ho i file
nell'hd) prima di risponderti e non ho piu' bisogno di far tradurre ad
ascii2uni. Adesso lo vedo pefetto ciao
 
-- 
Yoda
 

 for j in $(seq $1 $2); do
 
  O fai:
 
I=$1 ; while test $I -le $2 ; do ... ; done
(e da qualche parte nel ciclo incrementi I)
 
  oppure:
 
for ((J=$1; $J <= $2 ; J++)) ; do ... ; done
 
 
  Ciao,
 
 
Alessandro
 

 ascii2uni. Adesso lo vedo pefetto ciao
 
  Questo è quello che deve fare un client di email moderno e al passo
con le ultime RFC che standardizzano la firma e la crittografia PGP nei
messaggi di posta elettronica.
 
 
  Ciao,
 
 
Alessandro
 
 

 P.S. Hai visto Giuseppe con cut?! ciao
 
  Si, l'ho visto.  Visivamente è la soluzione più breve e comprensibile,
ma usa due comandi in pipeline.  La soluzione che usa la rimozione del
suffisso dalla variabile invece non ha bisogno di altro che la shell, ed
è quindi la più veloce.
 
 
  Ciao,
 
 
Alessandro
 

 for j in $(seq $1 $2); do
]zac[
 
"$@" = $..
 
Attenzioni agli spazi (a quelli che la shell considera separatori, IFS).
 
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
 


Risposta fuori tema, ho frainteso la richiesta.
Ma visto che ormai l'ho detta, c'è anche questa strada (split) per eliminare path
 
mindspill.net/computing/linux-notes/using-the-bash-ifs-variable-to-make-for-loops-split-with-non-whitespace-characters/
 

 *indegno* di esistere :D
 
I miei sistemi sono senza PHP e a malapena hanno C. E funzionano che è una
meraviglia. Capisco che tu conosca quel linguaggio indegno, ma evolverti in
qualcosa di migliore[1] non sarebbe male
 
Enrico
[1] Python, Go, se volete cito anche Ruby, ma solo perché tutto è meglio di PHP

 in modo da accettare qualunque tipo di path?
 
Probabilmente no perché il software è in produzione e non può essere cambiato
senza almeno un intervento programmato. Non sempre si può agire in totale
autonomia
 
Enrico

Il 11/06/19 11:26, Enrico Bianchi ha scritto:

Enrico non hai visto la mia emoticon.
Un'emoticon col sorriso cosa indica?
Battuta, ironia, ecc.
O sbaglio?

 autonomia
 
D'altro canto, e` strano che tale problema non
sia stato notato da altri...
 
bye,
 
-- 
 
piergiorgio

 sia stato notato da altri...
 
Magari fino ad ora si è proceduto per workaround...
 
Enrico

 Magari fino ad ora si è proceduto per workaround...
 
Esatto, è una soluzione provvisoria.

 "Ho visto cose che voi umani..."
 
:-)
 
Si, ma in questi casi, "casereccio" e
"produzione" nello stesso contesto, ci
sarebbe la gogna in sala mensa... :-)
 
bye,
 
-- 
 
piergiorgio

 familiare), che raggruppa i miei server locali :D
 
Ah! No! Addirittura "familiare"! :-)
 
Di solito, quando ho un problema, cerco
proprio cosa hanno fatto altri, nelle
stesse condizioni.
 
Se trovo che il problema e` comune, uso
una (la?) soluzione che viene proposta.
Dipende poi da quante vengano proposte...
 
Se trovo che il problema *non* e` comune,
inizio a farmi venire dubbi esistenziali.
In particolare, se tale problema sia proprio
tale oppure non mi sia io incartato da solo...
 
Dato che il SW in questione, "composer" mi
pare di aver capito, credo sia usato anche
da altre persone, allora immagino che si
avranno problemi simili, con soluzioni forse
gia` disponibili.
E se non sono disponibili, forse il problema
e` da rivedere in un'altra ottica...
 
bye,
 
-- 
 
piergiorgio